<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>初入React世界 | 房飞跃的博客</title>
    <meta name="generator" content="VuePress 1.8.2">
    <link rel="apple-touch-icon" href="/apple-touch-icon.png">
    <link rel="icon" href="/favicon.ico">
    <link rel="manifest" href="/manifest.json">
    <meta name="description" content="房飞跃的博客">
    <meta name="theme-color" content="#ffffff">
    
    <link rel="preload" href="/assets/css/0.styles.e57fdc06.css" as="style"><link rel="preload" href="/assets/js/app.8c5a7a92.js" as="script"><link rel="preload" href="/assets/js/2.8e30e130.js" as="script"><link rel="preload" href="/assets/js/40.fcf089d7.js" as="script"><link rel="preload" href="/assets/js/64.0323ed89.js" as="script"><link rel="prefetch" href="/assets/js/10.e695640a.js"><link rel="prefetch" href="/assets/js/100.fae9757f.js"><link rel="prefetch" href="/assets/js/101.d26f7a9a.js"><link rel="prefetch" href="/assets/js/102.e9b20f43.js"><link rel="prefetch" href="/assets/js/103.6d251ff3.js"><link rel="prefetch" href="/assets/js/104.5de918be.js"><link rel="prefetch" href="/assets/js/105.aead61a1.js"><link rel="prefetch" href="/assets/js/106.09a5decb.js"><link rel="prefetch" href="/assets/js/107.a44fc48a.js"><link rel="prefetch" href="/assets/js/108.cec63522.js"><link rel="prefetch" href="/assets/js/109.db1a4ed7.js"><link rel="prefetch" href="/assets/js/11.769ac82c.js"><link rel="prefetch" href="/assets/js/110.10914d38.js"><link rel="prefetch" href="/assets/js/111.2c0ddf25.js"><link rel="prefetch" href="/assets/js/112.c792ca07.js"><link rel="prefetch" href="/assets/js/113.a769ad8f.js"><link rel="prefetch" href="/assets/js/114.c1dca6a0.js"><link rel="prefetch" href="/assets/js/115.82e1fb4f.js"><link rel="prefetch" href="/assets/js/116.c927762b.js"><link rel="prefetch" href="/assets/js/117.5c14eedf.js"><link rel="prefetch" href="/assets/js/118.24861bb6.js"><link rel="prefetch" href="/assets/js/119.3fafaebf.js"><link rel="prefetch" href="/assets/js/12.23031504.js"><link rel="prefetch" href="/assets/js/120.a9ff8fae.js"><link rel="prefetch" href="/assets/js/121.3eb4b3a1.js"><link rel="prefetch" href="/assets/js/122.ff06cffe.js"><link rel="prefetch" href="/assets/js/123.aaf767a6.js"><link rel="prefetch" href="/assets/js/124.4daf257a.js"><link rel="prefetch" href="/assets/js/125.e7e71d3f.js"><link rel="prefetch" href="/assets/js/126.cdee6d86.js"><link rel="prefetch" href="/assets/js/127.aa133c3f.js"><link rel="prefetch" href="/assets/js/128.a8e7d8b2.js"><link rel="prefetch" href="/assets/js/129.dcca2d84.js"><link rel="prefetch" href="/assets/js/13.f37f647e.js"><link rel="prefetch" href="/assets/js/130.3925fb20.js"><link rel="prefetch" href="/assets/js/131.a3a759ed.js"><link rel="prefetch" href="/assets/js/132.84bb9bf9.js"><link rel="prefetch" href="/assets/js/133.30fceda7.js"><link rel="prefetch" href="/assets/js/134.e02f66bf.js"><link rel="prefetch" href="/assets/js/135.71a35d7f.js"><link rel="prefetch" href="/assets/js/136.77762773.js"><link rel="prefetch" href="/assets/js/137.b9741de3.js"><link rel="prefetch" href="/assets/js/138.59b64aa0.js"><link rel="prefetch" href="/assets/js/139.d81e68a1.js"><link rel="prefetch" href="/assets/js/14.0091824d.js"><link rel="prefetch" href="/assets/js/140.68388ddb.js"><link rel="prefetch" href="/assets/js/141.e69cc877.js"><link rel="prefetch" href="/assets/js/142.65fc1806.js"><link rel="prefetch" href="/assets/js/143.4f1e9b3d.js"><link rel="prefetch" href="/assets/js/144.5cf4bdda.js"><link rel="prefetch" href="/assets/js/145.1a1cdb18.js"><link rel="prefetch" href="/assets/js/146.ef4fe2c3.js"><link rel="prefetch" href="/assets/js/147.f5e5d206.js"><link rel="prefetch" href="/assets/js/148.07c7208f.js"><link rel="prefetch" href="/assets/js/149.fb71df8d.js"><link rel="prefetch" href="/assets/js/15.4e1991f3.js"><link rel="prefetch" href="/assets/js/150.771bcbfe.js"><link rel="prefetch" href="/assets/js/151.de02cd55.js"><link rel="prefetch" href="/assets/js/152.6a5b243d.js"><link rel="prefetch" href="/assets/js/153.c1c426d2.js"><link rel="prefetch" href="/assets/js/154.51e08a99.js"><link rel="prefetch" href="/assets/js/155.ab801c7a.js"><link rel="prefetch" href="/assets/js/156.e62111f0.js"><link rel="prefetch" href="/assets/js/157.67f19eb7.js"><link rel="prefetch" href="/assets/js/158.3e57553c.js"><link rel="prefetch" href="/assets/js/159.f01ea56a.js"><link rel="prefetch" href="/assets/js/16.aafe549d.js"><link rel="prefetch" href="/assets/js/160.81468500.js"><link rel="prefetch" href="/assets/js/161.8341c4c9.js"><link rel="prefetch" href="/assets/js/162.18cd1d1e.js"><link rel="prefetch" href="/assets/js/163.2ed65e27.js"><link rel="prefetch" href="/assets/js/164.1c0adbfd.js"><link rel="prefetch" href="/assets/js/165.4382f96e.js"><link rel="prefetch" href="/assets/js/166.47ad10ec.js"><link rel="prefetch" href="/assets/js/167.ee3e3de3.js"><link rel="prefetch" href="/assets/js/168.1273ebb0.js"><link rel="prefetch" href="/assets/js/169.bb6578e0.js"><link rel="prefetch" href="/assets/js/17.4548c40c.js"><link rel="prefetch" href="/assets/js/170.6aef0437.js"><link rel="prefetch" href="/assets/js/171.4818ad12.js"><link rel="prefetch" href="/assets/js/172.7f4674ed.js"><link rel="prefetch" href="/assets/js/173.25951cfa.js"><link rel="prefetch" href="/assets/js/174.604b8889.js"><link rel="prefetch" href="/assets/js/175.752d6221.js"><link rel="prefetch" href="/assets/js/176.ee6ccaf2.js"><link rel="prefetch" href="/assets/js/177.df3e7548.js"><link rel="prefetch" href="/assets/js/178.0c05bdea.js"><link rel="prefetch" href="/assets/js/179.fa300396.js"><link rel="prefetch" href="/assets/js/18.4a166581.js"><link rel="prefetch" href="/assets/js/180.78580e5a.js"><link rel="prefetch" href="/assets/js/181.c08c58e9.js"><link rel="prefetch" href="/assets/js/182.425fd44a.js"><link rel="prefetch" href="/assets/js/183.643e0376.js"><link rel="prefetch" href="/assets/js/184.28243fe4.js"><link rel="prefetch" href="/assets/js/185.145fafb0.js"><link rel="prefetch" href="/assets/js/186.9c005fb8.js"><link rel="prefetch" href="/assets/js/187.a1c8a8da.js"><link rel="prefetch" href="/assets/js/188.b78deff0.js"><link rel="prefetch" href="/assets/js/189.86432945.js"><link rel="prefetch" href="/assets/js/19.992da7e4.js"><link rel="prefetch" href="/assets/js/190.b6c616c9.js"><link rel="prefetch" href="/assets/js/191.d2a4a045.js"><link rel="prefetch" href="/assets/js/192.ce93c157.js"><link rel="prefetch" href="/assets/js/193.f45b56e8.js"><link rel="prefetch" href="/assets/js/194.60166b01.js"><link rel="prefetch" href="/assets/js/195.fea0fdcc.js"><link rel="prefetch" href="/assets/js/196.7f9353e4.js"><link rel="prefetch" href="/assets/js/197.2a8de731.js"><link rel="prefetch" href="/assets/js/198.6f3d807b.js"><link rel="prefetch" href="/assets/js/199.75028922.js"><link rel="prefetch" href="/assets/js/20.e27836ed.js"><link rel="prefetch" href="/assets/js/200.36fbe8e0.js"><link rel="prefetch" href="/assets/js/201.ca3a3d7d.js"><link rel="prefetch" href="/assets/js/202.8cc508cd.js"><link rel="prefetch" href="/assets/js/203.eb6662a4.js"><link rel="prefetch" href="/assets/js/204.a75edc0d.js"><link rel="prefetch" href="/assets/js/205.77cc7661.js"><link rel="prefetch" href="/assets/js/206.7cfc88ae.js"><link rel="prefetch" href="/assets/js/207.9d5b5377.js"><link rel="prefetch" href="/assets/js/208.9308a3b3.js"><link rel="prefetch" href="/assets/js/209.cbee10e7.js"><link rel="prefetch" href="/assets/js/21.9bc4424f.js"><link rel="prefetch" href="/assets/js/210.3dbd53b3.js"><link rel="prefetch" href="/assets/js/211.ffc0051e.js"><link rel="prefetch" href="/assets/js/212.420b9a23.js"><link rel="prefetch" href="/assets/js/213.da84f0aa.js"><link rel="prefetch" href="/assets/js/214.2a5308ff.js"><link rel="prefetch" href="/assets/js/215.bc87143e.js"><link rel="prefetch" href="/assets/js/216.f099b04d.js"><link rel="prefetch" href="/assets/js/217.39cc059e.js"><link rel="prefetch" href="/assets/js/218.3b588871.js"><link rel="prefetch" href="/assets/js/219.8c7c7f40.js"><link rel="prefetch" href="/assets/js/22.287b20ef.js"><link rel="prefetch" href="/assets/js/220.6a490188.js"><link rel="prefetch" href="/assets/js/221.a06fe7b9.js"><link rel="prefetch" href="/assets/js/222.0da34a82.js"><link rel="prefetch" href="/assets/js/223.6d6abad9.js"><link rel="prefetch" href="/assets/js/224.de157359.js"><link rel="prefetch" href="/assets/js/225.c733d3d1.js"><link rel="prefetch" href="/assets/js/226.039d453b.js"><link rel="prefetch" href="/assets/js/227.dbe84815.js"><link rel="prefetch" href="/assets/js/228.4850e3f3.js"><link rel="prefetch" href="/assets/js/229.322215a9.js"><link rel="prefetch" href="/assets/js/23.c1fc6d56.js"><link rel="prefetch" href="/assets/js/230.2469fb45.js"><link rel="prefetch" href="/assets/js/231.a77224ae.js"><link rel="prefetch" href="/assets/js/232.56534eb1.js"><link rel="prefetch" href="/assets/js/233.f69b682d.js"><link rel="prefetch" href="/assets/js/234.33fecaf9.js"><link rel="prefetch" href="/assets/js/235.3152a6d8.js"><link rel="prefetch" href="/assets/js/236.4a45a619.js"><link rel="prefetch" href="/assets/js/237.683796c5.js"><link rel="prefetch" href="/assets/js/238.4183baab.js"><link rel="prefetch" href="/assets/js/239.967342f3.js"><link rel="prefetch" href="/assets/js/24.c4266153.js"><link rel="prefetch" href="/assets/js/240.4ebdaa3e.js"><link rel="prefetch" href="/assets/js/241.3853f81e.js"><link rel="prefetch" href="/assets/js/242.0be00241.js"><link rel="prefetch" href="/assets/js/243.27a16565.js"><link rel="prefetch" href="/assets/js/244.4b6c0842.js"><link rel="prefetch" href="/assets/js/245.0ff5b09e.js"><link rel="prefetch" href="/assets/js/246.ec9708bc.js"><link rel="prefetch" href="/assets/js/247.33dd2e3f.js"><link rel="prefetch" href="/assets/js/248.e095c83d.js"><link rel="prefetch" href="/assets/js/249.e35dae0b.js"><link rel="prefetch" href="/assets/js/25.0bd19957.js"><link rel="prefetch" href="/assets/js/250.b7dda30b.js"><link rel="prefetch" href="/assets/js/251.373c219f.js"><link rel="prefetch" href="/assets/js/252.f02d8652.js"><link rel="prefetch" href="/assets/js/253.0129ab3b.js"><link rel="prefetch" href="/assets/js/254.05bc87ae.js"><link rel="prefetch" href="/assets/js/255.93959060.js"><link rel="prefetch" href="/assets/js/256.036268bb.js"><link rel="prefetch" href="/assets/js/257.4cfe4c46.js"><link rel="prefetch" href="/assets/js/258.70f49e1e.js"><link rel="prefetch" href="/assets/js/259.e92d7a7e.js"><link rel="prefetch" href="/assets/js/26.cd8cc5bc.js"><link rel="prefetch" href="/assets/js/260.24ecb139.js"><link rel="prefetch" href="/assets/js/261.32f0c433.js"><link rel="prefetch" href="/assets/js/262.aca4b5e9.js"><link rel="prefetch" href="/assets/js/263.0051554a.js"><link rel="prefetch" href="/assets/js/264.063d3092.js"><link rel="prefetch" href="/assets/js/265.de1fe60c.js"><link rel="prefetch" href="/assets/js/266.4407a594.js"><link rel="prefetch" href="/assets/js/267.9318dca9.js"><link rel="prefetch" href="/assets/js/268.b9696b4c.js"><link rel="prefetch" href="/assets/js/269.21743bc6.js"><link rel="prefetch" href="/assets/js/27.e0c9a2d1.js"><link rel="prefetch" href="/assets/js/270.64175904.js"><link rel="prefetch" href="/assets/js/271.ab988e51.js"><link rel="prefetch" href="/assets/js/272.40190656.js"><link rel="prefetch" href="/assets/js/273.124f97d6.js"><link rel="prefetch" href="/assets/js/274.ac2ae949.js"><link rel="prefetch" href="/assets/js/275.84112c31.js"><link rel="prefetch" href="/assets/js/276.5cd3a2f1.js"><link rel="prefetch" href="/assets/js/277.dfd266d2.js"><link rel="prefetch" href="/assets/js/278.2c22b507.js"><link rel="prefetch" href="/assets/js/279.143630b9.js"><link rel="prefetch" href="/assets/js/28.ee8b098b.js"><link rel="prefetch" href="/assets/js/280.e52e72d5.js"><link rel="prefetch" href="/assets/js/281.fa255716.js"><link rel="prefetch" href="/assets/js/282.33cf3680.js"><link rel="prefetch" href="/assets/js/283.8aaeb880.js"><link rel="prefetch" href="/assets/js/284.cce2c80c.js"><link rel="prefetch" href="/assets/js/285.649e1ab2.js"><link rel="prefetch" href="/assets/js/286.93d1a5fb.js"><link rel="prefetch" href="/assets/js/287.95ecc60d.js"><link rel="prefetch" href="/assets/js/288.d0316c60.js"><link rel="prefetch" href="/assets/js/289.96b0da90.js"><link rel="prefetch" href="/assets/js/29.f1800df7.js"><link rel="prefetch" href="/assets/js/290.a0ec1eb0.js"><link rel="prefetch" href="/assets/js/291.000c9293.js"><link rel="prefetch" href="/assets/js/292.aa442a45.js"><link rel="prefetch" href="/assets/js/293.ad41a62d.js"><link rel="prefetch" href="/assets/js/294.d01fa093.js"><link rel="prefetch" href="/assets/js/295.988cbaa2.js"><link rel="prefetch" href="/assets/js/296.b4376d7c.js"><link rel="prefetch" href="/assets/js/297.53d3839b.js"><link rel="prefetch" href="/assets/js/298.e41d3af5.js"><link rel="prefetch" href="/assets/js/299.7530e3f7.js"><link rel="prefetch" href="/assets/js/3.0318d431.js"><link rel="prefetch" href="/assets/js/30.e022632d.js"><link rel="prefetch" href="/assets/js/300.b89cf9f0.js"><link rel="prefetch" href="/assets/js/301.538c5d13.js"><link rel="prefetch" href="/assets/js/302.e61e98d4.js"><link rel="prefetch" href="/assets/js/303.e69fdf1f.js"><link rel="prefetch" href="/assets/js/304.12cf05d2.js"><link rel="prefetch" href="/assets/js/305.05630898.js"><link rel="prefetch" href="/assets/js/306.4423e4cb.js"><link rel="prefetch" href="/assets/js/307.ec499705.js"><link rel="prefetch" href="/assets/js/308.eae04a19.js"><link rel="prefetch" href="/assets/js/309.e8cdb29d.js"><link rel="prefetch" href="/assets/js/31.a2dfbc5f.js"><link rel="prefetch" href="/assets/js/310.3770a9fc.js"><link rel="prefetch" href="/assets/js/311.79ae7adb.js"><link rel="prefetch" href="/assets/js/312.fd3baefc.js"><link rel="prefetch" href="/assets/js/313.895f6dcd.js"><link rel="prefetch" href="/assets/js/314.85943d2f.js"><link rel="prefetch" href="/assets/js/315.69631810.js"><link rel="prefetch" href="/assets/js/316.b025621c.js"><link rel="prefetch" href="/assets/js/317.7b7974aa.js"><link rel="prefetch" href="/assets/js/318.972a129d.js"><link rel="prefetch" href="/assets/js/319.65a4d2cf.js"><link rel="prefetch" href="/assets/js/32.b143e718.js"><link rel="prefetch" href="/assets/js/320.e5635579.js"><link rel="prefetch" href="/assets/js/321.845573fa.js"><link rel="prefetch" href="/assets/js/322.0f95ad9a.js"><link rel="prefetch" href="/assets/js/323.f7d22184.js"><link rel="prefetch" href="/assets/js/324.eb027f24.js"><link rel="prefetch" href="/assets/js/325.f54af6ec.js"><link rel="prefetch" href="/assets/js/326.7a921d9f.js"><link rel="prefetch" href="/assets/js/327.e9c43c17.js"><link rel="prefetch" href="/assets/js/328.586efc33.js"><link rel="prefetch" href="/assets/js/329.47017c3f.js"><link rel="prefetch" href="/assets/js/33.e17e09ac.js"><link rel="prefetch" href="/assets/js/330.81032fbd.js"><link rel="prefetch" href="/assets/js/331.ce9966db.js"><link rel="prefetch" href="/assets/js/332.c28e794e.js"><link rel="prefetch" href="/assets/js/333.4564d08a.js"><link rel="prefetch" href="/assets/js/334.3b421837.js"><link rel="prefetch" href="/assets/js/335.b2b74b9d.js"><link rel="prefetch" href="/assets/js/336.9dd1e510.js"><link rel="prefetch" href="/assets/js/337.03042431.js"><link rel="prefetch" href="/assets/js/338.1bc0b80f.js"><link rel="prefetch" href="/assets/js/339.e517fc5c.js"><link rel="prefetch" href="/assets/js/34.f287ac3d.js"><link rel="prefetch" href="/assets/js/340.f90d2df3.js"><link rel="prefetch" href="/assets/js/341.eccb4ec1.js"><link rel="prefetch" href="/assets/js/342.b3386439.js"><link rel="prefetch" href="/assets/js/343.2ee6901d.js"><link rel="prefetch" href="/assets/js/344.e6913fc7.js"><link rel="prefetch" href="/assets/js/345.a72760e7.js"><link rel="prefetch" href="/assets/js/346.13984d25.js"><link rel="prefetch" href="/assets/js/347.6b59cbaf.js"><link rel="prefetch" href="/assets/js/348.f43d5e47.js"><link rel="prefetch" href="/assets/js/349.fe8641cf.js"><link rel="prefetch" href="/assets/js/35.5a1dace7.js"><link rel="prefetch" href="/assets/js/350.0ceb9652.js"><link rel="prefetch" href="/assets/js/351.08e70696.js"><link rel="prefetch" href="/assets/js/352.958f535b.js"><link rel="prefetch" href="/assets/js/353.51463d78.js"><link rel="prefetch" href="/assets/js/354.6169e165.js"><link rel="prefetch" href="/assets/js/355.10447463.js"><link rel="prefetch" href="/assets/js/356.32983151.js"><link rel="prefetch" href="/assets/js/357.39e998b6.js"><link rel="prefetch" href="/assets/js/358.1f40aee7.js"><link rel="prefetch" href="/assets/js/359.d1e82e86.js"><link rel="prefetch" href="/assets/js/36.b6f4332a.js"><link rel="prefetch" href="/assets/js/360.9096bf48.js"><link rel="prefetch" href="/assets/js/361.e2c0815a.js"><link rel="prefetch" href="/assets/js/362.66983024.js"><link rel="prefetch" href="/assets/js/363.d7f0691d.js"><link rel="prefetch" href="/assets/js/364.d96ddc65.js"><link rel="prefetch" href="/assets/js/365.c92ad624.js"><link rel="prefetch" href="/assets/js/366.dfd66280.js"><link rel="prefetch" href="/assets/js/367.01503521.js"><link rel="prefetch" href="/assets/js/368.8d83b9c1.js"><link rel="prefetch" href="/assets/js/369.f8e08a4f.js"><link rel="prefetch" href="/assets/js/37.f1a16008.js"><link rel="prefetch" href="/assets/js/370.70b912f3.js"><link rel="prefetch" href="/assets/js/371.dcefb388.js"><link rel="prefetch" href="/assets/js/372.a81a499a.js"><link rel="prefetch" href="/assets/js/373.94458b0f.js"><link rel="prefetch" href="/assets/js/374.a406f06f.js"><link rel="prefetch" href="/assets/js/375.87287c02.js"><link rel="prefetch" href="/assets/js/376.26088425.js"><link rel="prefetch" href="/assets/js/377.b9ee096c.js"><link rel="prefetch" href="/assets/js/378.7a1b6fa7.js"><link rel="prefetch" href="/assets/js/379.3e2b62fc.js"><link rel="prefetch" href="/assets/js/38.59f5160c.js"><link rel="prefetch" href="/assets/js/380.d741385f.js"><link rel="prefetch" href="/assets/js/381.afc0104a.js"><link rel="prefetch" href="/assets/js/382.a8c02915.js"><link rel="prefetch" href="/assets/js/383.7fca9756.js"><link rel="prefetch" href="/assets/js/384.d08aa931.js"><link rel="prefetch" href="/assets/js/385.c3ab471f.js"><link rel="prefetch" href="/assets/js/386.7314b80e.js"><link rel="prefetch" href="/assets/js/387.8db3a14a.js"><link rel="prefetch" href="/assets/js/388.f618a3b3.js"><link rel="prefetch" href="/assets/js/389.4d35947d.js"><link rel="prefetch" href="/assets/js/39.3cf9af40.js"><link rel="prefetch" href="/assets/js/390.a8e04e41.js"><link rel="prefetch" href="/assets/js/391.a31e9a62.js"><link rel="prefetch" href="/assets/js/392.d9321e46.js"><link rel="prefetch" href="/assets/js/393.6c4834d0.js"><link rel="prefetch" href="/assets/js/394.fd0a0ea4.js"><link rel="prefetch" href="/assets/js/395.0f27ab48.js"><link rel="prefetch" href="/assets/js/396.70044e25.js"><link rel="prefetch" href="/assets/js/397.07b2c0a6.js"><link rel="prefetch" href="/assets/js/398.ba95a9c5.js"><link rel="prefetch" href="/assets/js/399.8b310fbc.js"><link rel="prefetch" href="/assets/js/4.45f61616.js"><link rel="prefetch" href="/assets/js/400.7ff77c6c.js"><link rel="prefetch" href="/assets/js/401.840e0c7c.js"><link rel="prefetch" href="/assets/js/402.a722c16f.js"><link rel="prefetch" href="/assets/js/403.1a3c12fb.js"><link rel="prefetch" href="/assets/js/404.7da4d4a4.js"><link rel="prefetch" href="/assets/js/405.76a07310.js"><link rel="prefetch" href="/assets/js/406.176db1fd.js"><link rel="prefetch" href="/assets/js/407.ff3da33f.js"><link rel="prefetch" href="/assets/js/408.3b4dfb3a.js"><link rel="prefetch" href="/assets/js/409.05692a2e.js"><link rel="prefetch" href="/assets/js/41.3f0a746d.js"><link rel="prefetch" href="/assets/js/410.615dc40b.js"><link rel="prefetch" href="/assets/js/411.e542a59f.js"><link rel="prefetch" href="/assets/js/412.16fc0c97.js"><link rel="prefetch" href="/assets/js/413.b9f30c37.js"><link rel="prefetch" href="/assets/js/414.9629300e.js"><link rel="prefetch" href="/assets/js/415.5c12951e.js"><link rel="prefetch" href="/assets/js/416.3ede10bc.js"><link rel="prefetch" href="/assets/js/417.5bc08adb.js"><link rel="prefetch" href="/assets/js/418.0a54fe32.js"><link rel="prefetch" href="/assets/js/419.97ebd724.js"><link rel="prefetch" href="/assets/js/42.d0fdcdd4.js"><link rel="prefetch" href="/assets/js/420.d3f60a7a.js"><link rel="prefetch" href="/assets/js/421.6b187cc9.js"><link rel="prefetch" href="/assets/js/422.268b38aa.js"><link rel="prefetch" href="/assets/js/423.00f151fe.js"><link rel="prefetch" href="/assets/js/424.5d54e48d.js"><link rel="prefetch" href="/assets/js/425.b0e71df6.js"><link rel="prefetch" href="/assets/js/426.fb5d6c08.js"><link rel="prefetch" href="/assets/js/427.a7a42bdb.js"><link rel="prefetch" href="/assets/js/428.b41b80fb.js"><link rel="prefetch" href="/assets/js/429.aff3b223.js"><link rel="prefetch" href="/assets/js/43.7812871c.js"><link rel="prefetch" href="/assets/js/430.9bded6a2.js"><link rel="prefetch" href="/assets/js/431.fbd064dd.js"><link rel="prefetch" href="/assets/js/432.a0ccaf13.js"><link rel="prefetch" href="/assets/js/433.70729631.js"><link rel="prefetch" href="/assets/js/434.7ff21dc4.js"><link rel="prefetch" href="/assets/js/435.ba6f0c33.js"><link rel="prefetch" href="/assets/js/436.abcca44e.js"><link rel="prefetch" href="/assets/js/437.2b2333cb.js"><link rel="prefetch" href="/assets/js/438.93ea3d14.js"><link rel="prefetch" href="/assets/js/439.c1b946ea.js"><link rel="prefetch" href="/assets/js/44.d2bbbf62.js"><link rel="prefetch" href="/assets/js/440.a5c5071e.js"><link rel="prefetch" href="/assets/js/441.bad7a6f2.js"><link rel="prefetch" href="/assets/js/442.97a45e71.js"><link rel="prefetch" href="/assets/js/443.9dd7a744.js"><link rel="prefetch" href="/assets/js/444.b2e74ec9.js"><link rel="prefetch" href="/assets/js/445.181b11ad.js"><link rel="prefetch" href="/assets/js/446.1d43ea57.js"><link rel="prefetch" href="/assets/js/447.a75ca861.js"><link rel="prefetch" href="/assets/js/448.7e177e61.js"><link rel="prefetch" href="/assets/js/449.0e124a1f.js"><link rel="prefetch" href="/assets/js/45.2181b5c6.js"><link rel="prefetch" href="/assets/js/450.d18c5137.js"><link rel="prefetch" href="/assets/js/451.0296f837.js"><link rel="prefetch" href="/assets/js/452.1f5d56a5.js"><link rel="prefetch" href="/assets/js/453.6f67fa9b.js"><link rel="prefetch" href="/assets/js/454.d96cd4e8.js"><link rel="prefetch" href="/assets/js/455.488f2e23.js"><link rel="prefetch" href="/assets/js/456.264d0da2.js"><link rel="prefetch" href="/assets/js/457.329d4d26.js"><link rel="prefetch" href="/assets/js/458.d20d34f9.js"><link rel="prefetch" href="/assets/js/459.dd4fad09.js"><link rel="prefetch" href="/assets/js/46.d69710e9.js"><link rel="prefetch" href="/assets/js/460.e1f8580c.js"><link rel="prefetch" href="/assets/js/461.d47e1ab7.js"><link rel="prefetch" href="/assets/js/462.54b49f34.js"><link rel="prefetch" href="/assets/js/463.2d1bb289.js"><link rel="prefetch" href="/assets/js/464.28d2b2fe.js"><link rel="prefetch" href="/assets/js/465.474d09dd.js"><link rel="prefetch" href="/assets/js/466.3d79bf1d.js"><link rel="prefetch" href="/assets/js/467.0e38992e.js"><link rel="prefetch" href="/assets/js/468.23f8dbdb.js"><link rel="prefetch" href="/assets/js/469.424ab64e.js"><link rel="prefetch" href="/assets/js/47.fa77c18f.js"><link rel="prefetch" href="/assets/js/470.8e15adc4.js"><link rel="prefetch" href="/assets/js/471.e478b277.js"><link rel="prefetch" href="/assets/js/472.75eed247.js"><link rel="prefetch" href="/assets/js/473.676ac02f.js"><link rel="prefetch" href="/assets/js/474.ec676f10.js"><link rel="prefetch" href="/assets/js/475.0b3a7bb3.js"><link rel="prefetch" href="/assets/js/476.1dccc2bf.js"><link rel="prefetch" href="/assets/js/477.19774d6a.js"><link rel="prefetch" href="/assets/js/478.562bcdfb.js"><link rel="prefetch" href="/assets/js/479.0fdf39e1.js"><link rel="prefetch" href="/assets/js/48.55ba7067.js"><link rel="prefetch" href="/assets/js/480.32cb0959.js"><link rel="prefetch" href="/assets/js/481.39744803.js"><link rel="prefetch" href="/assets/js/482.82ff750c.js"><link rel="prefetch" href="/assets/js/483.59be5f3b.js"><link rel="prefetch" href="/assets/js/484.b47730ba.js"><link rel="prefetch" href="/assets/js/485.514e284f.js"><link rel="prefetch" href="/assets/js/486.8d407228.js"><link rel="prefetch" href="/assets/js/487.623afb9a.js"><link rel="prefetch" href="/assets/js/488.d575377d.js"><link rel="prefetch" href="/assets/js/49.369b2ef4.js"><link rel="prefetch" href="/assets/js/5.89e027e6.js"><link rel="prefetch" href="/assets/js/50.32e51808.js"><link rel="prefetch" href="/assets/js/51.48af1f55.js"><link rel="prefetch" href="/assets/js/52.0ff3366f.js"><link rel="prefetch" href="/assets/js/53.f663d530.js"><link rel="prefetch" href="/assets/js/54.57eabb55.js"><link rel="prefetch" href="/assets/js/55.00e0bdd0.js"><link rel="prefetch" href="/assets/js/56.b638bc9a.js"><link rel="prefetch" href="/assets/js/57.68420705.js"><link rel="prefetch" href="/assets/js/58.f0a325a2.js"><link rel="prefetch" href="/assets/js/59.30debc93.js"><link rel="prefetch" href="/assets/js/6.0db48d19.js"><link rel="prefetch" href="/assets/js/60.48490f44.js"><link rel="prefetch" href="/assets/js/61.26a984a9.js"><link rel="prefetch" href="/assets/js/62.f0add27d.js"><link rel="prefetch" href="/assets/js/63.07c42d31.js"><link rel="prefetch" href="/assets/js/65.c159a057.js"><link rel="prefetch" href="/assets/js/66.80e96020.js"><link rel="prefetch" href="/assets/js/67.42eabf7d.js"><link rel="prefetch" href="/assets/js/68.2a7e9954.js"><link rel="prefetch" href="/assets/js/69.4579e421.js"><link rel="prefetch" href="/assets/js/7.037ecfb1.js"><link rel="prefetch" href="/assets/js/70.4e7b95d4.js"><link rel="prefetch" href="/assets/js/71.5df75825.js"><link rel="prefetch" href="/assets/js/72.6239ec2a.js"><link rel="prefetch" href="/assets/js/73.c2458335.js"><link rel="prefetch" href="/assets/js/74.b86599e1.js"><link rel="prefetch" href="/assets/js/75.8d14cab7.js"><link rel="prefetch" href="/assets/js/76.82bf4b00.js"><link rel="prefetch" href="/assets/js/77.f5a890cc.js"><link rel="prefetch" href="/assets/js/78.f3c574f3.js"><link rel="prefetch" href="/assets/js/79.c9c56bf3.js"><link rel="prefetch" href="/assets/js/8.03d32196.js"><link rel="prefetch" href="/assets/js/80.24c4483b.js"><link rel="prefetch" href="/assets/js/81.e6653250.js"><link rel="prefetch" href="/assets/js/82.0da4ae5d.js"><link rel="prefetch" href="/assets/js/83.89a8c965.js"><link rel="prefetch" href="/assets/js/84.56206c88.js"><link rel="prefetch" href="/assets/js/85.0daf7cf7.js"><link rel="prefetch" href="/assets/js/86.0a17b684.js"><link rel="prefetch" href="/assets/js/87.f7cf9412.js"><link rel="prefetch" href="/assets/js/88.22341e3f.js"><link rel="prefetch" href="/assets/js/89.2166c8bb.js"><link rel="prefetch" href="/assets/js/9.a241a058.js"><link rel="prefetch" href="/assets/js/90.9440815d.js"><link rel="prefetch" href="/assets/js/91.5ea69e27.js"><link rel="prefetch" href="/assets/js/92.cea1c8dd.js"><link rel="prefetch" href="/assets/js/93.2e94ab93.js"><link rel="prefetch" href="/assets/js/94.1674ba0c.js"><link rel="prefetch" href="/assets/js/95.c6ba057e.js"><link rel="prefetch" href="/assets/js/96.ee719565.js"><link rel="prefetch" href="/assets/js/97.a814f163.js"><link rel="prefetch" href="/assets/js/98.748b1098.js"><link rel="prefetch" href="/assets/js/99.c6176c0d.js">
    <link rel="stylesheet" href="/assets/css/0.styles.e57fdc06.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><img src="/logo.png" alt="房飞跃的博客" class="logo"> <span class="site-name can-hide">房飞跃的博客</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="前端" class="dropdown-title"><span class="title">前端</span> <span class="arrow down"></span></button> <button type="button" aria-label="前端" class="mobile-dropdown-title"><span class="title">前端</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          Vue
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/books/深入浅出Vue.js/01.html" class="nav-link">
  深入浅出Vue
</a></li><li class="dropdown-subitem"><a href="/front/vue/vue/01.html" class="nav-link">
  Vue
</a></li><li class="dropdown-subitem"><a href="/front/vue/vue-router/01.html" class="nav-link">
  VueRouter
</a></li><li class="dropdown-subitem"><a href="/front/vue/Vuex/01.html" class="nav-link">
  Vuex
</a></li><li class="dropdown-subitem"><a href="/front/vue/vue3/01.html" class="nav-link">
  Vue3核心剖析
</a></li><li class="dropdown-subitem"><a href="/front/vue/Vue知识点简单梳理/01.html" class="nav-link">
  Vue知识点简单梳理
</a></li></ul></li><li class="dropdown-item"><h4>
          React
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/books/深入React技术栈/01.html" class="nav-link">
  深入React技术栈
</a></li><li class="dropdown-subitem"><a href="/front/react/React进阶实践指南/01.html" class="nav-link">
  React进阶实践指南
</a></li><li class="dropdown-subitem"><a href="/front/react/React知识点简单梳理/01.html" class="nav-link">
  React知识点简单梳理
</a></li></ul></li><li class="dropdown-item"><h4>
          混合开发
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/混合开发/01.html" class="nav-link">
  混合开发探究
</a></li></ul></li><li class="dropdown-item"><h4>
          TypeScript
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/ts/极简入门Typescript/01.html" class="nav-link">
  极简入门Typescript
</a></li></ul></li><li class="dropdown-item"><h4>
          Webpack
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/webpack/极简入门webpack/01.html" class="nav-link">
  极简入门
</a></li><li class="dropdown-subitem"><a href="/front/webpack/常见面试题/01.html" class="nav-link">
  常见面试题
</a></li></ul></li><li class="dropdown-item"><h4>
          设计模式
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/设计模式/JS设计模式核心原理和应用实践/01.html" class="nav-link">
  JS设计模式核心原理和应用实践
</a></li></ul></li><li class="dropdown-item"><h4>
          算法和数据结构
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/算法和数据结构/入门级算法/01.html" class="nav-link">
  入门级算法
</a></li><li class="dropdown-subitem"><a href="/front/算法和数据结构/常见算法/01.html" class="nav-link">
  常见算法
</a></li><li class="dropdown-subitem"><a href="/front/算法和数据结构/常见数据结构/01.html" class="nav-link">
  常见数据结构
</a></li><li class="dropdown-subitem"><a href="/front/算法和数据结构/前端算法与数据结构/01.html" class="nav-link">
  前端算法与数据结构
</a></li></ul></li><li class="dropdown-item"><h4>
          基础必备
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/base/html必备/01.html" class="nav-link">
  HTML必备
</a></li><li class="dropdown-subitem"><a href="/front/base/CSS必备/01.html" class="nav-link">
  CSS必备
</a></li><li class="dropdown-subitem"><a href="/front/base/JS基础/01.html" class="nav-link">
  JS基础
</a></li><li class="dropdown-subitem"><a href="/front/base/JS进阶/01.html" class="nav-link">
  JS进阶
</a></li><li class="dropdown-subitem"><a href="/front/base/JS练习/01.html" class="nav-link">
  JS练习
</a></li><li class="dropdown-subitem"><a href="/front/base/网络基础/01.html" class="nav-link">
  网络基础
</a></li><li class="dropdown-subitem"><a href="/books/JS高级程序设计/01.html" class="nav-link">
  JS高级程序设计
</a></li><li class="dropdown-subitem"><a href="/front/base/浏览器相关基础/01.html" class="nav-link">
  浏览器相关基础
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="电子" class="dropdown-title"><span class="title">电子</span> <span class="arrow down"></span></button> <button type="button" aria-label="电子" class="mobile-dropdown-title"><span class="title">电子</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          STM32
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/电子/STM32四轴飞行器/01.html" class="nav-link">
  STM32四轴飞行器
</a></li></ul></li><li class="dropdown-item"><h4>
          Arduino
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/电子/Arduino墙画机/01.html" class="nav-link">
  Arduino墙画机
</a></li><li class="dropdown-subitem"><a href="/电子/Arduino四轴飞行器/01.html" class="nav-link">
  Arduino四轴飞行器
</a></li><li class="dropdown-subitem"><a href="/电子/Arduino四足仿生机器人/01.html" class="nav-link">
  Arduino四足仿生机器人
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="关于" class="dropdown-title"><span class="title">关于</span> <span class="arrow down"></span></button> <button type="button" aria-label="关于" class="mobile-dropdown-title"><span class="title">关于</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/关于我/01.html" class="nav-link">
  关于我
</a></li><li class="dropdown-item"><!----> <a href="https://github.com/fangfeiyue" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Github
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="前端" class="dropdown-title"><span class="title">前端</span> <span class="arrow down"></span></button> <button type="button" aria-label="前端" class="mobile-dropdown-title"><span class="title">前端</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          Vue
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/books/深入浅出Vue.js/01.html" class="nav-link">
  深入浅出Vue
</a></li><li class="dropdown-subitem"><a href="/front/vue/vue/01.html" class="nav-link">
  Vue
</a></li><li class="dropdown-subitem"><a href="/front/vue/vue-router/01.html" class="nav-link">
  VueRouter
</a></li><li class="dropdown-subitem"><a href="/front/vue/Vuex/01.html" class="nav-link">
  Vuex
</a></li><li class="dropdown-subitem"><a href="/front/vue/vue3/01.html" class="nav-link">
  Vue3核心剖析
</a></li><li class="dropdown-subitem"><a href="/front/vue/Vue知识点简单梳理/01.html" class="nav-link">
  Vue知识点简单梳理
</a></li></ul></li><li class="dropdown-item"><h4>
          React
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/books/深入React技术栈/01.html" class="nav-link">
  深入React技术栈
</a></li><li class="dropdown-subitem"><a href="/front/react/React进阶实践指南/01.html" class="nav-link">
  React进阶实践指南
</a></li><li class="dropdown-subitem"><a href="/front/react/React知识点简单梳理/01.html" class="nav-link">
  React知识点简单梳理
</a></li></ul></li><li class="dropdown-item"><h4>
          混合开发
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/混合开发/01.html" class="nav-link">
  混合开发探究
</a></li></ul></li><li class="dropdown-item"><h4>
          TypeScript
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/ts/极简入门Typescript/01.html" class="nav-link">
  极简入门Typescript
</a></li></ul></li><li class="dropdown-item"><h4>
          Webpack
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/webpack/极简入门webpack/01.html" class="nav-link">
  极简入门
</a></li><li class="dropdown-subitem"><a href="/front/webpack/常见面试题/01.html" class="nav-link">
  常见面试题
</a></li></ul></li><li class="dropdown-item"><h4>
          设计模式
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/设计模式/JS设计模式核心原理和应用实践/01.html" class="nav-link">
  JS设计模式核心原理和应用实践
</a></li></ul></li><li class="dropdown-item"><h4>
          算法和数据结构
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/算法和数据结构/入门级算法/01.html" class="nav-link">
  入门级算法
</a></li><li class="dropdown-subitem"><a href="/front/算法和数据结构/常见算法/01.html" class="nav-link">
  常见算法
</a></li><li class="dropdown-subitem"><a href="/front/算法和数据结构/常见数据结构/01.html" class="nav-link">
  常见数据结构
</a></li><li class="dropdown-subitem"><a href="/front/算法和数据结构/前端算法与数据结构/01.html" class="nav-link">
  前端算法与数据结构
</a></li></ul></li><li class="dropdown-item"><h4>
          基础必备
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/base/html必备/01.html" class="nav-link">
  HTML必备
</a></li><li class="dropdown-subitem"><a href="/front/base/CSS必备/01.html" class="nav-link">
  CSS必备
</a></li><li class="dropdown-subitem"><a href="/front/base/JS基础/01.html" class="nav-link">
  JS基础
</a></li><li class="dropdown-subitem"><a href="/front/base/JS进阶/01.html" class="nav-link">
  JS进阶
</a></li><li class="dropdown-subitem"><a href="/front/base/JS练习/01.html" class="nav-link">
  JS练习
</a></li><li class="dropdown-subitem"><a href="/front/base/网络基础/01.html" class="nav-link">
  网络基础
</a></li><li class="dropdown-subitem"><a href="/books/JS高级程序设计/01.html" class="nav-link">
  JS高级程序设计
</a></li><li class="dropdown-subitem"><a href="/front/base/浏览器相关基础/01.html" class="nav-link">
  浏览器相关基础
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="电子" class="dropdown-title"><span class="title">电子</span> <span class="arrow down"></span></button> <button type="button" aria-label="电子" class="mobile-dropdown-title"><span class="title">电子</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          STM32
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/电子/STM32四轴飞行器/01.html" class="nav-link">
  STM32四轴飞行器
</a></li></ul></li><li class="dropdown-item"><h4>
          Arduino
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/电子/Arduino墙画机/01.html" class="nav-link">
  Arduino墙画机
</a></li><li class="dropdown-subitem"><a href="/电子/Arduino四轴飞行器/01.html" class="nav-link">
  Arduino四轴飞行器
</a></li><li class="dropdown-subitem"><a href="/电子/Arduino四足仿生机器人/01.html" class="nav-link">
  Arduino四足仿生机器人
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="关于" class="dropdown-title"><span class="title">关于</span> <span class="arrow down"></span></button> <button type="button" aria-label="关于" class="mobile-dropdown-title"><span class="title">关于</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/关于我/01.html" class="nav-link">
  关于我
</a></li><li class="dropdown-item"><!----> <a href="https://github.com/fangfeiyue" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Github
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div> <!----></nav>  <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>深入REACT技术栈</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/books/深入React技术栈/01.html" class="active sidebar-link">初入React世界</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/books/深入React技术栈/01.html#react简介" class="sidebar-link">React简介</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/01.html#jsx语法" class="sidebar-link">JSX语法</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/01.html#编写jsx注意项" class="sidebar-link">编写JSX注意项</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/01.html#react组件" class="sidebar-link">React组件</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/01.html#react数据流" class="sidebar-link">React数据流</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/01.html#react生命周期" class="sidebar-link">React生命周期</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/01.html#react-与-dom" class="sidebar-link">React 与 DOM</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/01.html#refs" class="sidebar-link">Refs</a></li></ul></li><li><a href="/books/深入React技术栈/02.html" class="sidebar-link">漫谈React</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/books/深入React技术栈/02.html#事件系统" class="sidebar-link">事件系统</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/02.html#表单" class="sidebar-link">表单</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/02.html#样式处理" class="sidebar-link">样式处理</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/02.html#组件间通信" class="sidebar-link">组件间通信</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/02.html#组件间抽象" class="sidebar-link">组件间抽象</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/02.html#组件性能优化" class="sidebar-link">组件性能优化</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/02.html#动画" class="sidebar-link">动画</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/02.html#自动化测试" class="sidebar-link">自动化测试</a></li></ul></li><li><a href="/books/深入React技术栈/03.html" class="sidebar-link">解读React源码</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/books/深入React技术栈/03.html#初探-react-源码" class="sidebar-link">初探 React 源码</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/03.html#virtual-dom-模型" class="sidebar-link">Virtual DOM 模型</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/03.html#生命周期的管理艺术" class="sidebar-link">生命周期的管理艺术</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/03.html#解密setstate机制" class="sidebar-link">解密setState机制</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/03.html#diff-算法" class="sidebar-link">diff 算法</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/03.html#react-patch-方法" class="sidebar-link">React Patch 方法</a></li></ul></li><li><a href="/books/深入React技术栈/04.html" class="sidebar-link">认识Flux架构模式</a></li><li><a href="/books/深入React技术栈/05.html" class="sidebar-link">深入Redux应用架构</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/books/深入React技术栈/05.html#redux-简介" class="sidebar-link">Redux 简介</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/05.html#redux-middleware" class="sidebar-link">Redux middleware</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/05.html#redux-异步流" class="sidebar-link">Redux 异步流</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/05.html#redux-与路由" class="sidebar-link">Redux 与路由</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/05.html#redux-与组件" class="sidebar-link">Redux 与组件</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/05.html#redux-应用实例" class="sidebar-link">Redux 应用实例</a></li></ul></li><li><a href="/books/深入React技术栈/06.html" class="sidebar-link">Redux高阶运用</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/books/深入React技术栈/06.html#高阶-reducer" class="sidebar-link">高阶 reducer</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/06.html#redux-与表单" class="sidebar-link">Redux 与表单</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/06.html#redux-crud-实战" class="sidebar-link">Redux CRUD 实战</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/06.html#redux-性能优化" class="sidebar-link">Redux 性能优化</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/06.html#解读-redux" class="sidebar-link">解读 Redux</a></li><li class="sidebar-sub-header"><a href="/books/深入React技术栈/06.html#解读-react-redux" class="sidebar-link">解读 react-redux</a></li></ul></li><li><a href="/books/深入React技术栈/07.html" class="sidebar-link">React服务端渲染</a></li><li><a href="/books/深入React技术栈/08.html" class="sidebar-link">玩转React可视化</a></li><li><a href="/books/深入React技术栈/09.html" class="sidebar-link">论文中期检查</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/books/深入React技术栈/09.html#前一阶段小结-中期报告内容" class="sidebar-link">前一阶段小结（中期报告内容）</a></li></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><p>本文为阅读<a href="https://item.jd.com/12068636.html" target="_blank" rel="noopener noreferrer">《深入React技术栈》<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>、<a href="https://reactjs.org/" target="_blank" rel="noopener noreferrer">React官方文档<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>、相关技术博客、工作实践，思考、整理而成，阅读书籍请支持正版。书籍非常不错，强烈推荐。如有侵权，请联系删除相关内容。</p> <h2 id="react简介"><a href="#react简介" class="header-anchor">#</a> React简介</h2> <p>React 是 Facebook 在 2013 年开源在 GitHub 上的 JavaScript 库。React把用户界面抽象成一个个组件，开发者通过组合这些组件，可以得到功能丰富、可交互的页面。</p> <ol><li>专注视图层</li></ol> <p>React专注于提供清晰、简洁的视图层解决方案。</p> <ol start="2"><li>Virtual DOM</li></ol> <p>在传统开发模式中更新页面需要手动操作DOM，这样不但性能消耗大，代码中充斥着过多的DOM操作也不利于代码的维护。React把真实DOM树转换成了Virtual DOM。当数据发生变化会重新计算Virtual DOM，将新、老VDOM进行对比，对发生变化的部分做批量更新。</p> <ol start="3"><li>函数式编程</li></ol> <p>React把重复构建UI的过程抽象成了组件，在给定参数的情况下约定渲染对应的 UI 界面。React 能充分利用很多函数式方法去减少冗余代码。此外，由于它本身就是简单函数，所以易于测试。</p> <p>React的特点：</p> <ol><li>声明式设计 − React采用声明范式，可以轻松描述应用。</li> <li>高效 − React通过对DOM的模拟，最大限度地减少与DOM的交互。</li> <li>灵活 − React可以与已知的库或框架很好地配合。</li> <li>JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ，但我们建议使用它。</li> <li>组件 − 通过 React 构建组件，使得代码更加容易得到复用，能够很好的应用在大项目的开发中。</li> <li>单向响应的数据流 − React 实现了单向响应的数据流，从而减少了重复代码，这也是它为什么比传统数据绑定更简单。</li></ol> <p>无论你现在正在使用什么技术栈，你都可以随时引入 React 来开发新特性，而不需要重写现有代码。React 还可以使用 Node 进行服务器渲染，或使用 React Native 开发原生移动应用。</p> <h2 id="jsx语法"><a href="#jsx语法" class="header-anchor">#</a> JSX语法</h2> <p>JSX是JavaScript语法扩展，用于在React中描述UI呈现。JSX允许我们像写HTML一样编写虚拟DOM。</p> <ol><li>在 JSX 中可以嵌入表达式</li></ol> <p>在JSX中可以嵌入任何表达式。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> name <span class="token operator">=</span> <span class="token string">'Josh Perez'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> element <span class="token operator">=</span> <span class="token operator">&lt;</span>h1<span class="token operator">&gt;</span>Hello<span class="token punctuation">,</span> <span class="token punctuation">{</span>name<span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>h1<span class="token operator">&gt;</span><span class="token punctuation">;</span>

ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span>
  element<span class="token punctuation">,</span>
  document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><ol start="2"><li>JSX可以用于if 语句和 for 循环的代码块中，可以将 JSX 赋值给变量也可以把 JSX 当作参数传入给函数，以及当做函数返回值返回。</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">getGreeting</span><span class="token punctuation">(</span><span class="token parameter">user</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>user<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token operator">&lt;</span>h1<span class="token operator">&gt;</span>Hello<span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token function">formatName</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token operator">!</span><span class="token operator">&lt;</span><span class="token operator">/</span>h1<span class="token operator">&gt;</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">return</span> <span class="token operator">&lt;</span>h1<span class="token operator">&gt;</span>Hello<span class="token punctuation">,</span> Stranger<span class="token punctuation">.</span><span class="token operator">&lt;</span><span class="token operator">/</span>h1<span class="token operator">&gt;</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><ol start="3"><li>JSX可以给标签定义属性，属性值为字符串时使用双引号包裹，属性值为变量时使用{}包裹，双引号和{}不能混在一起使用。</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> element1 <span class="token operator">=</span> <span class="token operator">&lt;</span>div tabIndex<span class="token operator">=</span><span class="token string">&quot;0&quot;</span><span class="token operator">&gt;</span><span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">&gt;</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> element2 <span class="token operator">=</span> <span class="token operator">&lt;</span>img src<span class="token operator">=</span><span class="token punctuation">{</span>user<span class="token punctuation">.</span>avatarUrl<span class="token punctuation">}</span><span class="token operator">&gt;</span><span class="token operator">&lt;</span><span class="token operator">/</span>img<span class="token operator">&gt;</span><span class="token punctuation">;</span>
</code></pre></div><ol start="4"><li>JSX中可以包含多个子元素</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> element <span class="token operator">=</span> <span class="token punctuation">(</span>
  <span class="token operator">&lt;</span>div<span class="token operator">&gt;</span>
    <span class="token operator">&lt;</span>h1<span class="token operator">&gt;</span>Hello<span class="token operator">!</span><span class="token operator">&lt;</span><span class="token operator">/</span>h1<span class="token operator">&gt;</span>
    <span class="token operator">&lt;</span>h2<span class="token operator">&gt;</span>Good to see you here<span class="token punctuation">.</span><span class="token operator">&lt;</span><span class="token operator">/</span>h2<span class="token operator">&gt;</span>
  <span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">&gt;</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><ol start="5"><li>Babel 会把 JSX 转译成一个名为 React.createElement() 函数调用。</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> element <span class="token operator">=</span> <span class="token punctuation">(</span>
  <span class="token operator">&lt;</span>h1 className<span class="token operator">=</span><span class="token string">&quot;greeting&quot;</span><span class="token operator">&gt;</span>
    Hello<span class="token punctuation">,</span> world<span class="token operator">!</span>
  <span class="token operator">&lt;</span><span class="token operator">/</span>h1<span class="token operator">&gt;</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>Babel编译后</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> element <span class="token operator">=</span> React<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span>
  <span class="token string">'h1'</span><span class="token punctuation">,</span>
  <span class="token punctuation">{</span>className<span class="token operator">:</span> <span class="token string">'greeting'</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token string">'Hello, world!'</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>上述代码调用React.createElement()后实际上它创建了一个这样的对象</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 注意：这是简化过的结构</span>
<span class="token keyword">const</span> element <span class="token operator">=</span> <span class="token punctuation">{</span>
  type<span class="token operator">:</span> <span class="token string">'h1'</span><span class="token punctuation">,</span>
  props<span class="token operator">:</span> <span class="token punctuation">{</span>
    className<span class="token operator">:</span> <span class="token string">'greeting'</span><span class="token punctuation">,</span>
    children<span class="token operator">:</span> <span class="token string">'Hello, world!'</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre></div><ol start="6"><li>JSX可以防止XSS攻击。</li></ol> <p>如下代码：</p> <div class="language-html extra-class"><pre class="language-html"><code><span class="token doctype"><span class="token punctuation">&lt;!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>en<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>UTF-8<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>viewport<span class="token punctuation">&quot;</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>width=device-width, initial-scale=1.0<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">&gt;</span></span>Document<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">&gt;</span></span>请您在输入框中输入您要评论的内容<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>input<span class="token punctuation">&quot;</span></span><span class="token punctuation">/&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>sendBtn<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>评论<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">&gt;</span></span>
    您评论的内容为：
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>content<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
  sendBtn<span class="token punctuation">.</span><span class="token function-variable function">onclick</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    content<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> input<span class="token punctuation">.</span>value
  <span class="token punctuation">}</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>当我们在输入框中输入如下代码</p> <div class="language-html extra-class"><pre class="language-html"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span><span class="token punctuation">&quot;</span></span> <span class="token attr-name">onerror</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>alert(<span class="token punctuation">'</span>开始攻击!<span class="token punctuation">'</span>)<span class="token punctuation">&quot;</span></span> <span class="token punctuation">/&gt;</span></span> 
</code></pre></div><p>点击评价按钮，页面会弹出“开始攻击弹窗”，触发恶意代码。</p> <p>当我们用React模拟相同功能时，则不会弹出”开始攻击弹窗“。这是因为React DOM 在渲染所有输入内容之前，默认会进行转义，所有的内容在渲染之前都被转换成了字符串。</p> <div class="language-html extra-class"><pre class="language-html"><code><span class="token doctype"><span class="token punctuation">&lt;!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>UTF-8<span class="token punctuation">&quot;</span></span> <span class="token punctuation">/&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">&gt;</span></span>Hello React!<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>https://cdn.staticfile.org/react/16.4.0/umd/react.development.js<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>example<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>text/babel<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
<span class="token keyword">class</span> <span class="token class-name">Evaluation</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">super</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>state <span class="token operator">=</span> <span class="token punctuation">{</span>
		content<span class="token operator">:</span><span class="token string">''</span><span class="token punctuation">,</span>
		value<span class="token operator">:</span> <span class="token string">''</span>
	<span class="token punctuation">}</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  
  <span class="token function-variable function">sendEvaluation</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  	<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setState</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
		content<span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>value
	<span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  <span class="token function-variable function">inputVal</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  	<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setState</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
		value<span class="token operator">:</span> e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>value
	<span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token punctuation">(</span>
      <span class="token operator">&lt;</span>div<span class="token operator">&gt;</span>
          <span class="token operator">&lt;</span>p<span class="token operator">&gt;</span>请您在输入框中输入您要评论的内容<span class="token operator">&lt;</span><span class="token operator">/</span>p<span class="token operator">&gt;</span>
		  <span class="token operator">&lt;</span>input onBlur<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>inputVal<span class="token punctuation">}</span><span class="token operator">/</span><span class="token operator">&gt;</span>
		  <span class="token operator">&lt;</span>button onClick<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>sendEvaluation<span class="token punctuation">}</span><span class="token operator">&gt;</span>发布评论<span class="token operator">&lt;</span><span class="token operator">/</span>button<span class="token operator">&gt;</span>
		  <span class="token operator">&lt;</span>div<span class="token operator">&gt;</span>
			您评论的内容为：
			<span class="token operator">&lt;</span>p id<span class="token operator">=</span><span class="token string">&quot;content&quot;</span><span class="token operator">&gt;</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>content<span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>p<span class="token operator">&gt;</span>
		  <span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">&gt;</span>
      <span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">&gt;</span>
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span>
  <span class="token operator">&lt;</span>Evaluation <span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
  document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'example'</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><h2 id="编写jsx注意项"><a href="#编写jsx注意项" class="header-anchor">#</a> 编写JSX注意项</h2> <ol><li>定义标签时，只允许被一个标签包裹。原因是一个标签会被转译成对应的 React.createElement 调用方法，最外层没有被包裹，无法转译成方法调用。</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 报错</span>
<span class="token keyword">const</span> component1 <span class="token operator">=</span> <span class="token operator">&lt;</span>span<span class="token operator">&gt;</span>name<span class="token operator">&lt;</span><span class="token operator">/</span>span<span class="token operator">&gt;</span><span class="token operator">&lt;</span>span<span class="token operator">&gt;</span> value<span class="token operator">&lt;</span><span class="token operator">/</span>span<span class="token operator">&gt;</span>

<span class="token comment">// 正确</span>
<span class="token keyword">const</span> component2 <span class="token operator">=</span> <span class="token operator">&lt;</span>div<span class="token operator">&gt;</span><span class="token operator">&lt;</span>span<span class="token operator">&gt;</span>name<span class="token operator">&lt;</span><span class="token operator">/</span>span<span class="token operator">&gt;</span><span class="token operator">&lt;</span>span<span class="token operator">&gt;</span> value<span class="token operator">&lt;</span><span class="token operator">/</span>span<span class="token operator">&gt;</span><span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">&gt;</span>
</code></pre></div><ol start="2"><li>标签一定要闭合。</li> <li>DOM元素首字母小写，组件元素首字母大写。</li> <li>注释，JSX最后被转换成JS，因此可以使用JS中添加注释的方法添加注释，在一个组件的子元素位置使用注释要用 {} 包起来。示例代码如下</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> App <span class="token operator">=</span> <span class="token punctuation">(</span>
  <span class="token operator">&lt;</span>Nav<span class="token operator">&gt;</span>
    <span class="token punctuation">{</span><span class="token comment">/* 节点注释 */</span><span class="token punctuation">}</span>
    <span class="token operator">&lt;</span>Person
      <span class="token comment">/* 多行
         注释 */</span>
      name<span class="token operator">=</span><span class="token punctuation">{</span>window<span class="token punctuation">.</span>isLoggedIn <span class="token operator">?</span> window<span class="token punctuation">.</span>name <span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">}</span>
    <span class="token operator">/</span><span class="token operator">&gt;</span>
  <span class="token operator">&lt;</span><span class="token operator">/</span>Nav<span class="token operator">&gt;</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><ol start="5"><li>DOM 元素的属性是标准规范属性，但有两个例外——class 和 for，因为在JS中这两个都是关键字，需要做转换</li></ol> <ul><li>class 属性改为 className；</li> <li>for 属性改为 htmlFor。
组件元素的属性是自定义属性，也就是组件所需的参数，在写自定义属性的时候，都由标准写法改为小驼峰写法。</li></ul> <ol start="6"><li>JSX特有的属性</li></ol> <ul><li>省略 Boolean 属性值会导致 JSX 认为 bool 值设为了 true。</li></ul> <div class="language-js extra-class"><pre class="language-js"><code><span class="token operator">&lt;</span>Checkbox checked<span class="token operator">=</span><span class="token punctuation">{</span><span class="token boolean">true</span><span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">&gt;</span> <span class="token comment">//等价于</span>
<span class="token operator">&lt;</span>Checkbox checked <span class="token operator">/</span><span class="token operator">&gt;</span>
</code></pre></div><ul><li>展开属性</li></ul> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> data <span class="token operator">=</span> <span class="token punctuation">{</span> name<span class="token operator">:</span> <span class="token string">'foo'</span><span class="token punctuation">,</span> value<span class="token operator">:</span> <span class="token string">'bar'</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> component <span class="token operator">=</span> <span class="token operator">&lt;</span>Component <span class="token punctuation">{</span><span class="token operator">...</span>data<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">;</span>
</code></pre></div><ul><li>自定义 HTML 属性
在JSX中，往DOM元素传入自定义属性需要使用<code>data-</code>前缀</li></ul> <div class="language-js extra-class"><pre class="language-js"><code><span class="token operator">&lt;</span>div data<span class="token operator">-</span>attr<span class="token operator">=</span><span class="token string">&quot;xxx&quot;</span><span class="token operator">&gt;</span>content<span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">&gt;</span>
</code></pre></div><p>自定义标签支持任何属性。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token operator">&lt;</span>my<span class="token operator">-</span>component custom<span class="token operator">-</span>attr<span class="token operator">=</span><span class="token string">&quot;foo&quot;</span> <span class="token operator">/</span><span class="token operator">&gt;</span>
</code></pre></div><ol start="7"><li>JavaScript 属性表达式</li></ol> <p>属性值要使用表达式，只要用 {} 替换 &quot;&quot; 即可：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> person <span class="token operator">=</span> <span class="token operator">&lt;</span>Person name<span class="token operator">=</span><span class="token punctuation">{</span>window<span class="token punctuation">.</span>isLoggedIn <span class="token operator">?</span> window<span class="token punctuation">.</span>name <span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">;</span>
<span class="token comment">// 对应输出</span>
<span class="token keyword">const</span> person <span class="token operator">=</span> React<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span>
  Person<span class="token punctuation">,</span>
  <span class="token punctuation">{</span>name<span class="token operator">:</span> window<span class="token punctuation">.</span>isLoggedIn <span class="token operator">?</span> window<span class="token punctuation">.</span>name <span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">}</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> content <span class="token operator">=</span> <span class="token operator">&lt;</span>Container<span class="token operator">&gt;</span><span class="token punctuation">{</span>window<span class="token punctuation">.</span>isLoggedIn <span class="token operator">?</span> <span class="token operator">&lt;</span>Nav <span class="token operator">/</span><span class="token operator">&gt;</span> <span class="token operator">:</span> <span class="token operator">&lt;</span>Login <span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>Container<span class="token operator">&gt;</span><span class="token punctuation">;</span>
<span class="token comment">// 对应输出</span>
<span class="token keyword">const</span> content <span class="token operator">=</span> React<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span>
  Container<span class="token punctuation">,</span>
  <span class="token keyword">null</span><span class="token punctuation">,</span>
  window<span class="token punctuation">.</span>isLoggedIn <span class="token operator">?</span> React<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span>Nav<span class="token punctuation">)</span> <span class="token operator">:</span> React<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span>Login<span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><ol start="8"><li>HTML 转义。React 会将所有要显示到 DOM 的字符串转义，防止 XSS。React 提供了 dangerouslySetInnerHTML 属性。正如其名，它的作用就是避免 React 转义字符。</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token operator">&lt;</span>div dangerouslySetInnerHTML<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span>__html<span class="token operator">:</span> <span class="token string">'cc &amp;copy; 2015'</span><span class="token punctuation">}</span><span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">&gt;</span>
</code></pre></div><h2 id="react组件"><a href="#react组件" class="header-anchor">#</a> React组件</h2> <h3 id="react组件的构建方法"><a href="#react组件的构建方法" class="header-anchor">#</a> React组件的构建方法</h3> <ol><li>React.createClass(React 16后已废弃)</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> Text <span class="token operator">=</span> React<span class="token punctuation">.</span><span class="token function">createClass</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token function">getDefaultProps</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token punctuation">{</span>
      text<span class="token operator">:</span> <span class="token string">'hello'</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>

  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> <span class="token punctuation">{</span> text <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">;</span>
　
    <span class="token keyword">return</span> <span class="token punctuation">(</span>
      <span class="token operator">&lt;</span>span<span class="token operator">&gt;</span><span class="token punctuation">{</span>text<span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>span<span class="token operator">&gt;</span>
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><ol start="2"><li>ES6 classes</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> Component <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span><span class="token punctuation">;</span>
　
<span class="token keyword">class</span> <span class="token class-name">Text</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">super</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
　
  <span class="token keyword">static</span> defaultProps <span class="token operator">=</span> <span class="token punctuation">{</span>
    text<span class="token operator">:</span> <span class="token string">'hello'</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
　
  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> <span class="token punctuation">{</span> text <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">;</span>

    <span class="token keyword">return</span> <span class="token punctuation">(</span>
      <span class="token operator">&lt;</span>span<span class="token operator">&gt;</span><span class="token punctuation">{</span>text<span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>span<span class="token operator">&gt;</span>
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p>React 的所有组件都继承自顶层类 React.Component。它的定义非常简洁，只是初始化了 React.Component 方法，声明了 props、context、refs 等，并在原型上定义了 setState 和 forceUpdate 方法。</p> <ol start="3"><li>无状态函数</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> <span class="token function-variable function">Text</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> text <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token operator">&lt;</span>span<span class="token operator">&gt;</span><span class="token punctuation">{</span>text<span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>span<span class="token operator">&gt;</span>
</code></pre></div><p>无状态组件没有state和生命周期方法，在合适的情况下我们应该使用无状态组件进行开发。因为无状态组件不像上述两种方法在调用时会创建新实例，它创建时始终保持了一个实例，避免了不必要的检查和内存分配，做到了内部优化。</p> <p>函数组件和类组件有什么不同呢？详见 <a href="https://overreacted.io/zh-hans/how-are-function-components-different-from-classes/" target="_blank" rel="noopener noreferrer">函数式组件与类组件有何不同？<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <h2 id="react数据流"><a href="#react数据流" class="header-anchor">#</a> React数据流</h2> <p>React中的数据流是自顶向下单向流动的，也就是从父组件到子组件，state和props是React组件中非常重要的概念</p> <h3 id="state"><a href="#state" class="header-anchor">#</a> state</h3> <p>state用于管理组件内部状态，这些状态我们通过setState方法来进行改变，当状态改变的后组件会尝试重新渲染。</p> <p>下面以一个简单的计数器为例：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> Component <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span>

<span class="token keyword">class</span> <span class="token class-name">Count</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">super</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>state <span class="token operator">=</span> <span class="token punctuation">{</span>
      count<span class="token operator">:</span> <span class="token number">0</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
  <span class="token function-variable function">handleClick</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setState</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      count<span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>count <span class="token operator">+</span> <span class="token number">1</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token operator">&lt;</span>span onClick<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>handleClick<span class="token punctuation">}</span><span class="token operator">&gt;</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>count<span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>span<span class="token operator">&gt;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span>
  <span class="token operator">&lt;</span>Count<span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
  document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'app'</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>当我们点击文本时，会触发setState方法并更新state，使得组件重新渲染。</p> <p>注意：一个生命周期内所有的 setState 方法会合并操作。</p> <h3 id="props"><a href="#props" class="header-anchor">#</a> props</h3> <p>props用于父子组件间通信，子组件内不能直接改变props的值，defaultProps静态变量可以定义props的默认值。在 React 中有一个重要且内置的 prop——children，它代表组件的子组件集合。如果顶层组件初始化 props，那么 React 会向下遍历整棵组件树，重新尝试渲染所有相关的子组件。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// ...</span>

<span class="token keyword">class</span> <span class="token class-name">Count</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span>
  <span class="token keyword">static</span> defaultProps <span class="token operator">=</span> <span class="token punctuation">{</span>
    count<span class="token operator">:</span> <span class="token number">0</span>
  <span class="token punctuation">}</span>
  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token operator">&lt;</span>span<span class="token operator">&gt;</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">.</span>count<span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>span<span class="token operator">&gt;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span>
  <span class="token operator">&lt;</span>Count count<span class="token operator">=</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">}</span><span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
  document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'example'</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><h2 id="react生命周期"><a href="#react生命周期" class="header-anchor">#</a> React生命周期</h2> <p>React生命周期在React 16进行了较大变更，这里我们以React 16为分界线简要介绍下React的生命周期。</p> <h3 id="react-16-前的生命周期"><a href="#react-16-前的生命周期" class="header-anchor">#</a> React 16 前的生命周期</h3> <p><img src="/assets/img/2.e1c4dfdb.png" alt=""></p> <ol><li>初始化阶段</li></ol> <p>constructor用来做一些组件初始化操作，比如初始化state</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> Component <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span>

<span class="token keyword">class</span> <span class="token class-name">Count</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// 调用基类的构造函数并把基类的props注入到子组件</span>
    <span class="token keyword">super</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><ol start="2"><li>挂载阶段</li></ol> <ul><li>componentWillMount</li></ul> <p>在组件挂在到DOM前调用且只调用一次</p> <ul><li>render</li></ul> <p>render函数会插入jsx生成的dom结构，react会生成一份虚拟dom树，在每一次组件更新时，react会通过diff算法比较更新前后的新旧DOM树，找到最小的有差异的DOM节点，并重新渲染</p> <ul><li>componentDidMount</li></ul> <p>组件挂载到DOM后调用且只调用一次</p> <ol start="3"><li>更新</li></ol> <p>如上图在Updation阶段触发更新的有两种情况，一种是组件的props改变了，一种是组件的state改变了。</p> <p>在React中组件更新一般有两种情况：</p> <p>(1) 父组件重新render导致子组件更新，如果此时我们并不想子组件也跟着更新，可以使用shouldComponentUpdate方法阻止子组件的更新。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">class</span> <span class="token class-name">Count</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span>
   <span class="token function">shouldComponentUpdate</span><span class="token punctuation">(</span><span class="token parameter">nextProps</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
      <span class="token keyword">if</span><span class="token punctuation">(</span>nextProps<span class="token punctuation">.</span>count <span class="token operator">===</span> <span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">.</span>count<span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">false</span> <span class="token comment">// 返回false阻止更新</span>
      <span class="token punctuation">}</span>
      <span class="token keyword">return</span> <span class="token boolean">true</span>
    <span class="token punctuation">}</span>
    <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token operator">&lt;</span>div<span class="token operator">&gt;</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">.</span>count<span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">&gt;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p>如果Count组件中没有使用props，可以直接在shouldComponentUpdate返回false，阻止Count组件渲染。</p> <p>(2) 组件内调用setState，无论state有没有变化都会引起组件的重新渲染，这时可以使用shouldComponentUpdate进行优化，只有state变化后组件才重新渲染。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">class</span> <span class="token class-name">Count</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">super</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>state <span class="token operator">=</span> <span class="token punctuation">{</span>
      count<span class="token operator">:</span> <span class="token number">0</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
  <span class="token function">shouldComponentUpdate</span><span class="token punctuation">(</span><span class="token parameter">nextProps<span class="token punctuation">,</span> nextState</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span>nextState<span class="token punctuation">.</span>count <span class="token operator">===</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>count<span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token comment">// 如果count的值没有发生变化，组件不重新渲染</span>
      <span class="token keyword">return</span> <span class="token boolean">false</span>
    <span class="token punctuation">}</span>
	  <span class="token keyword">return</span> <span class="token boolean">true</span>
  <span class="token punctuation">}</span>
  <span class="token function-variable function">handleClick</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setState</span><span class="token punctuation">(</span><span class="token punctuation">{</span> 
      count<span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>count
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token operator">&lt;</span>span onClick<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>handleClick<span class="token punctuation">}</span><span class="token operator">&gt;</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>count<span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>span<span class="token operator">&gt;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><ul><li>componentWillReceiveProps(nextProps)</li></ul> <p>如果组件是由父组件更新 props 而更新的，那么在 shouldComponentUpdate 之前会先执行 componentWillReceiveProps 方法。</p> <p>在组件接收到一个新的 prop (更新后)时被调用，参数nextProps是父组件传给当前组件的新props，这个方法中需要对比nextProps和this.props，将nextProps的state做为当前组件的state，从而重新渲染组件</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">componentWillReceiveProps</span> <span class="token punctuation">(</span><span class="token parameter">nextProps</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  nextProps<span class="token punctuation">.</span>count <span class="token operator">!==</span> <span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">.</span>count<span class="token operator">&amp;&amp;</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setState</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      count<span class="token operator">:</span>nextProps<span class="token punctuation">.</span>count
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><ul><li>shouldComponentUpdate(nextProps, nextState)</li></ul> <p>返回一个布尔值。在组件接收到新的props或者state时被调用，返回true组件继续执行更新操作，返回false组件停止更新操作，可以用来减少组件的不必要渲染，优化性能。在初始化时或者使用forceUpdate时不被调用。</p> <ul><li>componentWillUpdate (nextProps,nextState)</li></ul> <p>在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。</p> <ul><li>render</li></ul> <p>render函数会插入jsx生成的dom结构，react会生成一份虚拟dom树，在每一次组件更新时，react会通过diff算法比较更新前后的新旧DOM树，找到最小的有差异的DOM节点，并重新渲染</p> <ul><li>componentDidUpdate(prevProps,prevState)</li></ul> <p>在组件完成更新后立即调用。在初始化时不会被调用。</p> <ol start="4"><li>卸载</li></ol> <p>componentWillUnmount</p> <p>在组件被卸载前调用，一般用于一些清理工作，如清理定时器、事件绑定等等，以免造成内存泄露。</p> <h3 id="react-16-3后的组件生命周期"><a href="#react-16-3后的组件生命周期" class="header-anchor">#</a> React 16.3后的组件生命周期</h3> <p>React16.3之后新增了两个新的生命周期函数。</p> <ul><li>getDerivedStateFromProps
因为在React推出Fiber后之前的某些生命周期方法就不合适了，因为要开启async rendering，在render函数之前的所有函数，都有可能被执行多次。</li></ul> <p>随着getDerivedStateFromProps的推出，deprecate了一组生命周期API</p> <p>（1） componentWillReceiveProps</p> <p>（2）componentWillMount</p> <p>（3）componentWillUpdate</p> <p>除了shouldComponentUpdate之外，render之前的所有生命周期函数全灭。</p> <p>getDerivedStateFromProps是一个静态函数，不能访问this。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">static</span> <span class="token function">getDerivedStateFromProps</span><span class="token punctuation">(</span><span class="token parameter">nextProps<span class="token punctuation">,</span> prevState</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">//根据nextProps和prevState计算出预期的状态改变，返回结果会被送给setState</span>
<span class="token punctuation">}</span>
</code></pre></div><ul><li>getSnapshotBeforeUpdate</li></ul> <p>这个函数在render之后执行，执行的时候DOM元素还没有更新，因此有机会去获取一个DOM信息，计算得到一个snapshot，这个snapshot会作为componentDidUpdate的第三个参数传入。</p> <p>官方示例：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">class</span> <span class="token class-name">ScrollingList</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">super</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>listRef <span class="token operator">=</span> React<span class="token punctuation">.</span><span class="token function">createRef</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token function">getSnapshotBeforeUpdate</span><span class="token punctuation">(</span><span class="token parameter">prevProps<span class="token punctuation">,</span> prevState</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// Are we adding new items to the list?</span>
    <span class="token comment">// Capture the scroll position so we can adjust scroll later.</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>prevProps<span class="token punctuation">.</span>list<span class="token punctuation">.</span>length <span class="token operator">&lt;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">.</span>list<span class="token punctuation">.</span>length<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> list <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>listRef<span class="token punctuation">.</span>current<span class="token punctuation">;</span>
      <span class="token keyword">return</span> list<span class="token punctuation">.</span>scrollHeight <span class="token operator">-</span> list<span class="token punctuation">.</span>scrollTop<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token function">componentDidUpdate</span><span class="token punctuation">(</span><span class="token parameter">prevProps<span class="token punctuation">,</span> prevState<span class="token punctuation">,</span> snapshot</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// If we have a snapshot value, we've just added new items.</span>
    <span class="token comment">// Adjust scroll so these new items don't push the old ones out of view.</span>
    <span class="token comment">// (snapshot here is the value returned from getSnapshotBeforeUpdate)</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>snapshot <span class="token operator">!==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> list <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>listRef<span class="token punctuation">.</span>current<span class="token punctuation">;</span>
      list<span class="token punctuation">.</span>scrollTop <span class="token operator">=</span> list<span class="token punctuation">.</span>scrollHeight <span class="token operator">-</span> snapshot<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>

  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token punctuation">(</span>
      <span class="token operator">&lt;</span>div ref<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>listRef<span class="token punctuation">}</span><span class="token operator">&gt;</span><span class="token punctuation">{</span><span class="token comment">/* ...contents... */</span><span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">&gt;</span>
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p>React16.3生命周期图：</p> <p><img src="/assets/img/1.1fb35602.png" alt=""></p> <p>从图中可以看出，在Updating过程中，setState或者forceUpdate触发的更新不会调用getDerivedStateFromProps方法。</p> <p>React 16.4版本对其进行了修改：</p> <p><img src="/assets/img/3.5c82b4f4.png" alt=""></p> <p>让getDerivedStateFromProps方法无论是Mounting还是Updating，无论是因为什么引起的Updating，全部都会被调用。</p> <h2 id="react-与-dom"><a href="#react-与-dom" class="header-anchor">#</a> React 与 DOM</h2> <p>react-dom的package提供了可在应用顶层使用的 DOM（DOM-specific）方法，如果有需要，你可以把这些方法用于 React 模型以外的地方。不过一般情况下，大部分组件都不需要使用这个模块。ReactDOM 的关注点在 DOM 上，因此只适用于 Web 端。在 React 组件的开发实现中，我们并不会用到 ReactDOM，只有在顶层组件以及由于 React 模型所限而不得不操作 DOM 的时候，才会使用它。</p> <ol><li>findDOMNode</li></ol> <p>语法：ReactDOM.findDOMNode(component)</p> <p>我们可以通过ReactDOM.findDOMNode方法获取到组件对应的已渲染的真实DOM元素。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> Component <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> ReactDOM <span class="token keyword">from</span> <span class="token string">'react-dom'</span><span class="token punctuation">;</span>

<span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span>
  <span class="token function">componentDidMount</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// this 为当前组件的实例</span>
    <span class="token keyword">const</span> dom <span class="token operator">=</span> ReactDOM<span class="token punctuation">.</span><span class="token function">findDOMNode</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p>findDOMNode() 不能用在无状态组件上。在大多数情况下，不推荐使用该方法，因为它会破坏组件的抽象结构，严格模式下该方法已弃用。如果在开发中实在想获取真实DOM元素，可以尝试绑定一个 ref 到 DOM 节点上。</p> <ol start="2"><li>render</li></ol> <p>语法：ReactDOM.render(element, container[, callback])</p> <p>该方法把element挂载到container，并返回对该组件的引用。如果是无状态组件，render 会返回 null。当组件在初次渲染之后再次更新时，React 不会把整个组件重新渲染一次，而会用它高效的 DOM diff 算法做局部的更新。如果提供了可选的回调函数，该回调将在组件被渲染或更新之后被执行。</p> <p>ReactDOM.render() 目前会返回对根组件 ReactComponent 实例的引用。 但是，目前应该避免使用返回的引用，因为它是历史遗留下来的内容，而且在未来版本的 React 中，组件渲染在某些情况下可能会是异步的。 如果你真的需要获得对根组件 ReactComponent 实例的引用，那么推荐为根元素添加 callback ref。</p> <p>使用 ReactDOM.render() 对服务端渲染容器进行 hydrate 操作的方式已经被废弃，并且会在 React 17 被移除。作为替代，请使用 hydrate()。</p> <ol start="3"><li>unmountComponentAtNode</li></ol> <p>语法：ReactDOM.unmountComponentAtNode(container)</p> <p>作用：从 DOM 中卸载组件，会将其事件处理器（event handlers）和 state 一并清除。如果指定容器上没有对应已挂载的组件，这个函数什么也不会做。如果组件被移除将会返回 true，如果没有组件可被移除将会返回 false。</p> <ol start="4"><li>createPortal</li></ol> <p>语法：ReactDOM.createPortal(child, container)</p> <p>作用：创建 portal。Portal 将提供一种将子节点渲染到 DOM 节点中的方式，该节点存在于 DOM 组件的层次结构之外。</p> <h2 id="refs"><a href="#refs" class="header-anchor">#</a> Refs</h2> <p>在某些情况下如果需要操作真实DOM，React提供了Refs，允许我们访问 DOM 节点或在 render 方法中创建的 React 元素。</p> <p>虽然React提供了直接操作DOM的方法，但是不可乱用，我们应该尽量避免使用 refs 来做任何可以通过声明式实现来完成的事情。</p> <p>下面是几个适合使用 refs 的情况：</p> <ul><li>管理焦点，文本选择或媒体播放。</li> <li>触发强制动画。</li> <li>集成第三方 DOM 库。</li></ul> <p>在React16.3之前通过字符串或者回调函数的形式获取，在React 16.3中引入了React.createRef API。在React 16.8中引入了React.useRef API。</p> <p>下面的代码简单列举了四种ref的使用方法：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// string ref</span>
<span class="token keyword">class</span> <span class="token class-name">MyComponent1</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span>
  <span class="token function">componentDidMount</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>refs<span class="token punctuation">.</span>myRef<span class="token punctuation">.</span><span class="token function">focus</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token operator">&lt;</span>input ref<span class="token operator">=</span><span class="token string">&quot;myRef&quot;</span> <span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token comment">// callback ref</span>
<span class="token keyword">class</span> <span class="token class-name">MyComponent2</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span>
  <span class="token function">componentDidMount</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>myRef<span class="token punctuation">.</span><span class="token function">focus</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token operator">&lt;</span>input ref<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span><span class="token parameter">ele</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>myRef <span class="token operator">=</span> ele<span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token comment">// React.createRef()</span>
<span class="token keyword">class</span> <span class="token class-name">MyComponent3</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">super</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// 使用React.createRef()创建ref并绑定到一个实例属性上，以便可以在整个组件中使用</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>myRef <span class="token operator">=</span> React<span class="token punctuation">.</span><span class="token function">createRef</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token function">componentDidMount</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>myRef<span class="token punctuation">.</span>current<span class="token punctuation">.</span><span class="token function">focus</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// 通过ref 属性将创建的Refs添加到 React 元素上</span>
    <span class="token keyword">return</span> <span class="token operator">&lt;</span>div ref<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>myRef<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token comment">// React.useRef</span>
<span class="token keyword">function</span> <span class="token function">MyComponent4</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> myRef <span class="token operator">=</span> React<span class="token punctuation">.</span><span class="token function">useRef</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">)</span>
  <span class="token keyword">return</span> <span class="token operator">&lt;</span>span ref<span class="token operator">=</span><span class="token punctuation">{</span>myRef<span class="token punctuation">}</span><span class="token operator">&gt;</span>hello world<span class="token operator">&lt;</span><span class="token operator">/</span>span<span class="token operator">&gt;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>React官方文档中已明确提出string ref这种方式会被移除，所以开发时不要再使用这中方式了。我们可能会疑惑为啥string ref这种形式被废弃了呢，从上面简单的例子来看，string ref也挺方便的呀。这是因为：</p> <p><a href="https://github.com/facebook/react/pull/8333" target="_blank" rel="noopener noreferrer">some issues<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p><a href="https://news.ycombinator.com/edit?id=12093234" target="_blank" rel="noopener noreferrer">String refs are bad in quite a few ways<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p>这个网站需要梯子，这里放下截图</p> <p><img src="/assets/img/4.6f5eba5c.png" alt=""></p> <ol><li>string ref 无法被组合，例如一个第三方库的父组件已经给子组件传递了 ref，那么我们就无法再在子组件上添加 ref 了，而 callback ref 可完美解决此问题。</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">/** string ref **/</span>
<span class="token keyword">class</span> <span class="token class-name">Parent</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span>
  <span class="token function">componentDidMount</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// 可获取到 this.refs.childRef</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>refs<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token operator">&lt;</span>input ref<span class="token operator">=</span><span class="token string">&quot;childRef&quot;</span><span class="token operator">/</span><span class="token operator">&gt;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span>
  <span class="token function">componentDidMount</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// this.refs.child 无法获取到</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>refs<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token punctuation">(</span>
      <span class="token operator">&lt;</span>Parent<span class="token operator">&gt;</span>
        <span class="token operator">&lt;</span>input ref<span class="token operator">=</span><span class="token string">&quot;child&quot;</span> <span class="token operator">/</span><span class="token operator">&gt;</span>
      <span class="token operator">&lt;</span><span class="token operator">/</span>Parent<span class="token operator">&gt;</span>
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token comment">/** callback ref **/</span>
<span class="token keyword">class</span> <span class="token class-name">Parent</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span>
  <span class="token function">componentDidMount</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// 可以获取到 child ref</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'parent'</span><span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>childRef<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> <span class="token punctuation">{</span> children <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token operator">&lt;</span>input ref<span class="token operator">=</span><span class="token punctuation">{</span><span class="token parameter">child</span><span class="token operator">=&gt;</span><span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span>childRef <span class="token operator">=</span>child<span class="token punctuation">;</span> children<span class="token punctuation">.</span>ref <span class="token operator">&amp;&amp;</span> children<span class="token punctuation">.</span><span class="token function">ref</span><span class="token punctuation">(</span>child<span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator">/</span><span class="token operator">&gt;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span>
  <span class="token function">componentDidMount</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// 可以获取到 child ref</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'app'</span><span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>child<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token punctuation">(</span>
      <span class="token operator">&lt;</span>Parent<span class="token operator">&gt;</span>
        <span class="token operator">&lt;</span>input ref<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span><span class="token parameter">child</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
          <span class="token keyword">this</span><span class="token punctuation">.</span>child <span class="token operator">=</span> child<span class="token punctuation">;</span>
        <span class="token punctuation">}</span><span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">&gt;</span>
      <span class="token operator">&lt;</span><span class="token operator">/</span>Parent<span class="token operator">&gt;</span>
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><ol start="2"><li>string ref 不适用于Flow之类的静态分析。 Flow不能猜测框架可以使字符串ref“出现”在react上的神奇效果，以及它的类型（可能有所不同）。 回调引用比静态分析更友好。</li> <li>字符串ref的所有者由当前执行的组件确定。这意味着，使用常见的“渲染回调”模式(e.g. <code>&lt;DataTable renderRow={this.renderRow} /&gt;</code>)，错误的组件将拥有ref(它将在DataTable上结束，而不是你定义的组件renderRow)。</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">class</span> <span class="token class-name">MyComponent</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span>
  <span class="token function-variable function">renderRow</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">index</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// string ref 会挂载在 DataTable this 上</span>
    <span class="token keyword">return</span> <span class="token operator">&lt;</span>input ref<span class="token operator">=</span><span class="token punctuation">{</span><span class="token string">'input-'</span> <span class="token operator">+</span> index<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">;</span>

    <span class="token comment">// callback ref 会挂载在 MyComponent this 上</span>
    <span class="token keyword">return</span> <span class="token operator">&lt;</span>input ref<span class="token operator">=</span><span class="token punctuation">{</span><span class="token parameter">input</span> <span class="token operator">=&gt;</span> <span class="token keyword">this</span><span class="token punctuation">[</span><span class="token string">'input-'</span> <span class="token operator">+</span> index<span class="token punctuation">]</span> <span class="token operator">=</span> input<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
 
  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token operator">&lt;</span>DataTable data<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">.</span>data<span class="token punctuation">}</span> renderRow<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>renderRow<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">&gt;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><ol start="4"><li>string ref 强制React跟踪当前正在执行的组件。 这是有问题的，因为它使react模块处于有状态，并在捆绑中复制react模块时导致奇怪的错误。在 reconciliation 阶段，React Element 创建和更新的过程中，ref 会被封装为一个闭包函数，等待 commit 阶段被执行，这会对 React 的性能产生一些影响。</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">coerceRef</span><span class="token punctuation">(</span>
  <span class="token parameter">returnFiber<span class="token operator">:</span> Fiber<span class="token punctuation">,</span>
  current<span class="token operator">:</span> Fiber <span class="token operator">|</span> <span class="token keyword">null</span><span class="token punctuation">,</span>
  element<span class="token operator">:</span> ReactElement<span class="token punctuation">,</span></span>
<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token operator">...</span>
  <span class="token keyword">const</span> stringRef <span class="token operator">=</span> <span class="token string">''</span> <span class="token operator">+</span> element<span class="token punctuation">.</span>ref<span class="token punctuation">;</span>
  <span class="token comment">// 从 fiber 中得到实例</span>
  <span class="token keyword">let</span> inst <span class="token operator">=</span> ownerFiber<span class="token punctuation">.</span>stateNode<span class="token punctuation">;</span>
  
  <span class="token comment">// ref 闭包函数</span>
  <span class="token keyword">const</span> <span class="token function-variable function">ref</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> refs <span class="token operator">=</span> inst<span class="token punctuation">.</span>refs <span class="token operator">===</span> emptyObject <span class="token operator">?</span> <span class="token punctuation">(</span>inst<span class="token punctuation">.</span>refs <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token operator">:</span> inst<span class="token punctuation">.</span>refs<span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>value <span class="token operator">===</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">delete</span> refs<span class="token punctuation">[</span>stringRef<span class="token punctuation">]</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
      refs<span class="token punctuation">[</span>stringRef<span class="token punctuation">]</span> <span class="token operator">=</span> value<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
  ref<span class="token punctuation">.</span>_stringRef <span class="token operator">=</span> stringRef<span class="token punctuation">;</span>
  <span class="token keyword">return</span> ref<span class="token punctuation">;</span>
  <span class="token operator">...</span>
<span class="token punctuation">}</span>
</code></pre></div><ol start="5"><li>在根组件上使用无法生效。</li></ol> <div class="language-js extra-class"><pre class="language-js"><code>ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span><span class="token operator">&lt;</span>App ref<span class="token operator">=</span><span class="token string">&quot;app&quot;</span> <span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">,</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'main'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><ol start="6"><li>对于静态类型较不友好，当使用 string ref 时，必须显式声明 refs 的类型，无法完成自动推导。</li> <li>编译器无法将 string ref 与其 refs 上对应的属性进行混淆，而使用 callback ref，可被混淆。</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">/** string ref，无法混淆 */</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>refs<span class="token punctuation">.</span>myRef
<span class="token operator">&lt;</span>div ref<span class="token operator">=</span><span class="token string">&quot;myRef&quot;</span><span class="token operator">&gt;</span><span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">&gt;</span>

<span class="token comment">/** callback ref, 可以混淆 */</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>myRef
<span class="token operator">&lt;</span>div ref<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span><span class="token parameter">dom</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span>myRef <span class="token operator">=</span> dom<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator">&gt;</span><span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">&gt;</span>

<span class="token keyword">this</span><span class="token punctuation">.</span>r
<span class="token operator">&lt;</span>div ref<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span>r <span class="token operator">=</span> e<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator">&gt;</span><span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">&gt;</span>
</code></pre></div><p>我们再来看下createRef 和 callback ref，从语义上来看createRef更直观一些且如果 ref 回调函数是以内联函数的方式定义的，在更新过程中它会被执行两次，第一次传入参数 null，然后第二次会传入参数 DOM 元素。这是因为在每次渲染时会创建一个新的函数实例，所以 React 清空旧的 ref 并且设置新的。通过将 ref 的回调函数定义成 class 的绑定函数的方式可以避免上述问题，但是大多数情况下它是无关紧要的。</p> <p>ref 回调函数以内联函数的方式定义：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">class</span> <span class="token class-name">Count</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">super</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>state <span class="token operator">=</span> <span class="token punctuation">{</span>
      count<span class="token operator">:</span> <span class="token number">0</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>

  <span class="token function-variable function">handleClick</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setState</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      count<span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>count <span class="token operator">+</span> <span class="token number">1</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token punctuation">(</span>
      <span class="token operator">&lt;</span>span ref<span class="token operator">=</span><span class="token punctuation">{</span>
        <span class="token parameter">ele</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
          <span class="token keyword">this</span><span class="token punctuation">.</span>spanRef <span class="token operator">=</span> ele
          <span class="token comment">// ref 回调函数是以内联函数的方式定义的，在更新过程中它会被执行两次</span>
          console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'执行了'</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span>
        onClick<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>handleClick<span class="token punctuation">}</span>
      <span class="token operator">&gt;</span>
        <span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>count<span class="token punctuation">}</span>
      <span class="token operator">&lt;</span><span class="token operator">/</span>span<span class="token operator">&gt;</span>
    <span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span>
  <span class="token operator">&lt;</span>Count <span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
  document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'example'</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>ref 的回调函数定义为class 的绑定函数：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">class</span> <span class="token class-name">Count</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">super</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>state <span class="token operator">=</span> <span class="token punctuation">{</span>
      count<span class="token operator">:</span> <span class="token number">0</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">setSpanRef</span> <span class="token operator">=</span> <span class="token parameter">ele</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>spanRef <span class="token operator">=</span> ele
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'执行了'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>

  <span class="token function-variable function">handleClick</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setState</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      count<span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>count <span class="token operator">+</span> <span class="token number">1</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token punctuation">(</span>
      <span class="token operator">&lt;</span>span
      <span class="token comment">// ref 的回调函数定义成 class 的绑定函数时，只执行一次</span>
        ref<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>setSpanRef<span class="token punctuation">}</span>
        onClick<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>handleClick<span class="token punctuation">}</span>
      <span class="token operator">&gt;</span>
        <span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>count<span class="token punctuation">}</span>
      <span class="token operator">&lt;</span><span class="token operator">/</span>span<span class="token operator">&gt;</span>
    <span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span>
  <span class="token operator">&lt;</span>Count <span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
  document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'example'</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>上面我们简单列举了下四种创建ref的方式和些许区别。下面我们</p> <h3 id="访问refs"><a href="#访问refs" class="header-anchor">#</a> 访问Refs</h3> <p>当 ref 被传递给 render 中的元素时，对该节点的引用可以在 ref 的 current 属性中被访问。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> node <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>myRef<span class="token punctuation">.</span>current<span class="token punctuation">;</span>
</code></pre></div><p>默认不能在函数组件上使用ref属性，因为没有实例。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">DangerousTip</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token operator">&lt;</span>span ref<span class="token operator">=</span><span class="token string">&quot;3&quot;</span><span class="token operator">&gt;</span>禁止触碰！！！<span class="token operator">&lt;</span><span class="token operator">/</span>span<span class="token operator">&gt;</span>
<span class="token punctuation">}</span>

<span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">super</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>myRef <span class="token operator">=</span> React<span class="token punctuation">.</span><span class="token function">createRef</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?</span>
    <span class="token keyword">return</span> <span class="token operator">&lt;</span>DangerousTip ref<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>myRef<span class="token punctuation">}</span><span class="token operator">/</span><span class="token operator">&gt;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span>
  <span class="token operator">&lt;</span>App <span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
  document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'example'</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>如果非想在函数组件上使用ref可以使用forwardRef</p> <p>我们可以通过React.useRef()在函数组件内部使用ref属性了只要它指向一个 DOM 元素或 class 组件</p> <div class="language-html extra-class"><pre class="language-html"><code><span class="token doctype"><span class="token punctuation">&lt;!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>UTF-8<span class="token punctuation">&quot;</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">&gt;</span></span>Hello World<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>https://unpkg.com/react@17/umd/react.development.js<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>https://unpkg.com/react-dom@17/umd/react-dom.development.js<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>

    <span class="token comment">&lt;!-- Don't use this in production: --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>https://unpkg.com/@babel/standalone/babel.min.js<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>root<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>text/babel<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
      <span class="token keyword">const</span> <span class="token punctuation">{</span> useRef <span class="token punctuation">}</span> <span class="token operator">=</span> React
      <span class="token keyword">const</span> <span class="token punctuation">{</span> render <span class="token punctuation">}</span> <span class="token operator">=</span> ReactDOM

      <span class="token keyword">function</span> <span class="token function">DangerousTip</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">const</span> myRef <span class="token operator">=</span> <span class="token function">useRef</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">)</span>
        <span class="token keyword">const</span> <span class="token function-variable function">printContent</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>myRef<span class="token punctuation">.</span>current<span class="token punctuation">.</span>innerText<span class="token punctuation">)</span>
        <span class="token keyword">return</span> <span class="token operator">&lt;</span>span ref<span class="token operator">=</span><span class="token punctuation">{</span>myRef<span class="token punctuation">}</span> onClick<span class="token operator">=</span><span class="token punctuation">{</span>printContent<span class="token punctuation">}</span><span class="token operator">&gt;</span>禁止触摸！！！<span class="token operator">&lt;</span><span class="token operator">/</span>span<span class="token operator">&gt;</span>
      <span class="token punctuation">}</span>

      <span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span>
        <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          <span class="token keyword">return</span> <span class="token operator">&lt;</span>DangerousTip<span class="token operator">/</span><span class="token operator">&gt;</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span>

      <span class="token function">render</span><span class="token punctuation">(</span>
        <span class="token operator">&lt;</span>App<span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
        document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span>
      <span class="token punctuation">)</span><span class="token punctuation">;</span>

    </span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>我们不能在类组件中使用useRef创建ref</p> <div class="language-html extra-class"><pre class="language-html"><code><span class="token doctype"><span class="token punctuation">&lt;!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>UTF-8<span class="token punctuation">&quot;</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">&gt;</span></span>Hello World<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>https://unpkg.com/react@17/umd/react.development.js<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>https://unpkg.com/react-dom@17/umd/react-dom.development.js<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>

    <span class="token comment">&lt;!-- Don't use this in production: --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>https://unpkg.com/@babel/standalone/babel.min.js<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>root<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>text/babel<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
      <span class="token keyword">const</span> <span class="token punctuation">{</span> useRef <span class="token punctuation">}</span> <span class="token operator">=</span> React
      <span class="token keyword">const</span> <span class="token punctuation">{</span> render <span class="token punctuation">}</span> <span class="token operator">=</span> ReactDOM

      <span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span>
        <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          <span class="token keyword">super</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span>
          <span class="token keyword">this</span><span class="token punctuation">.</span>myRef <span class="token operator">=</span> <span class="token function">useRef</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
        <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          <span class="token comment">// Invalid hook call. Hooks can only be called inside of the body of a function component.</span>
          <span class="token keyword">return</span> <span class="token operator">&lt;</span>input ref<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>myRef<span class="token punctuation">}</span><span class="token operator">/</span><span class="token operator">&gt;</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span>

      <span class="token function">render</span><span class="token punctuation">(</span>
        <span class="token operator">&lt;</span>App<span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
        document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span>
      <span class="token punctuation">)</span><span class="token punctuation">;</span>

    </span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><h3 id="react-forwardref"><a href="#react-forwardref" class="header-anchor">#</a> React.forwardRef</h3> <p>在某些情况下可能会希望父组件能引用子组件的DOM节点，这个使用可以使用Refs 转发。Ref 转发是一项将 ref 自动地通过组件传递到其一子组件的技巧。对于大多数应用中的组件来说，这通常不是必需的。</p> <p>我们可以通过React.forwardRef 来获取传递给它的 ref。下面是一个简单的实例，点击APP组件中的button在控制台打印出input中输出的内容</p> <div class="language-html extra-class"><pre class="language-html"><code><span class="token doctype"><span class="token punctuation">&lt;!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>UTF-8<span class="token punctuation">&quot;</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">&gt;</span></span>Hello React<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>https://unpkg.com/react@17/umd/react.development.js<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>https://unpkg.com/react-dom@17/umd/react-dom.development.js<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>

    <span class="token comment">&lt;!-- Don't use this in production: --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>https://unpkg.com/@babel/standalone/babel.min.js<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>root<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>text/babel<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
      <span class="token keyword">const</span> <span class="token punctuation">{</span> useRef<span class="token punctuation">,</span> forwardRef<span class="token punctuation">,</span> createRef <span class="token punctuation">}</span> <span class="token operator">=</span> React
      <span class="token keyword">const</span> <span class="token punctuation">{</span> render <span class="token punctuation">}</span> <span class="token operator">=</span> ReactDOM

      <span class="token keyword">const</span> Input <span class="token operator">=</span> <span class="token function">forwardRef</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">props<span class="token punctuation">,</span> ref</span><span class="token punctuation">)</span><span class="token operator">=&gt;</span><span class="token operator">&lt;</span>input ref<span class="token operator">=</span><span class="token punctuation">{</span>ref<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">)</span>

      <span class="token keyword">function</span> <span class="token function">App</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// const inputRef = useRef(null)</span>
        <span class="token keyword">const</span> inputRef <span class="token operator">=</span> <span class="token function">createRef</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token keyword">const</span> <span class="token function-variable function">print</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>inputRef<span class="token punctuation">.</span>current<span class="token punctuation">.</span>value<span class="token punctuation">)</span>
        
        <span class="token keyword">return</span> <span class="token punctuation">(</span>
          <span class="token operator">&lt;</span>div<span class="token operator">&gt;</span>
            评价：<span class="token operator">&lt;</span>Input ref<span class="token operator">=</span><span class="token punctuation">{</span>inputRef<span class="token punctuation">}</span><span class="token operator">/</span><span class="token operator">&gt;</span>
            <span class="token operator">&lt;</span>button onClick<span class="token operator">=</span><span class="token punctuation">{</span>print<span class="token punctuation">}</span><span class="token operator">&gt;</span>提交<span class="token operator">&lt;</span><span class="token operator">/</span>button<span class="token operator">&gt;</span>
          <span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">&gt;</span>
        <span class="token punctuation">)</span>
      <span class="token punctuation">}</span>
      <span class="token function">render</span><span class="token punctuation">(</span>
        <span class="token operator">&lt;</span>App<span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
        document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span>
      <span class="token punctuation">)</span><span class="token punctuation">;</span>

    </span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>简要描述下步骤：</p> <ol><li>我们通过调用 React.useRef 创建了一个 React ref 并将其赋值给 inputRef 变量。</li> <li>我们通过指定 ref 为 JSX 属性，将其向下传递给<code>&lt;Input ref={ref}&gt;</code>。</li> <li>React 传递 ref 给 forwardRef 内函数 (props, ref) =&gt; ...，作为其第二个参数。</li> <li>我们向下转发该 ref 参数到<code>&lt;input ref={ref}/&gt;</code>，将其指定为 JSX 属性。</li> <li>当 ref 挂载完成，ref.current 将指向<code>&lt;input&gt;</code> DOM 节点。</li></ol> <div class="custom-block warning"><p class="custom-block-title">注意</p> <p>第二个参数 ref 只在使用 React.forwardRef 定义组件时存在。常规函数和 class 组件不接收 ref 参数，且 props 中也不存在 ref。</p> <p>Ref 转发不仅限于 DOM 组件，你也可以转发 refs 到 class 组件实例中。</p></div> <p>可能你会问，如果我使用的是低版本的react，不支持React.forwardRef怎么办呢？可以使用 ref 作为特殊名字的 prop 直接传递。</p> <div class="language-html extra-class"><pre class="language-html"><code><span class="token doctype"><span class="token punctuation">&lt;!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>UTF-8<span class="token punctuation">&quot;</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">&gt;</span></span>Hello React<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>https://unpkg.com/react@17/umd/react.development.js<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>https://unpkg.com/react-dom@17/umd/react-dom.development.js<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>

    <span class="token comment">&lt;!-- Don't use this in production: --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>https://unpkg.com/@babel/standalone/babel.min.js<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>root<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>text/babel<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
      <span class="token keyword">const</span> <span class="token punctuation">{</span> useRef<span class="token punctuation">,</span> forwardRef<span class="token punctuation">,</span> createRef <span class="token punctuation">}</span> <span class="token operator">=</span> React
      <span class="token keyword">const</span> <span class="token punctuation">{</span> render <span class="token punctuation">}</span> <span class="token operator">=</span> ReactDOM

      <span class="token keyword">function</span> <span class="token function">Input</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token operator">&lt;</span>input ref<span class="token operator">=</span><span class="token punctuation">{</span>props<span class="token punctuation">.</span>inputRef<span class="token punctuation">}</span><span class="token operator">/</span><span class="token operator">&gt;</span>
      <span class="token punctuation">}</span>
      <span class="token keyword">function</span> <span class="token function">App</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// const inputRef = useRef(null)</span>
        <span class="token keyword">const</span> inputRef <span class="token operator">=</span> <span class="token function">createRef</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token keyword">const</span> <span class="token function-variable function">onSubmit</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>inputRef<span class="token punctuation">.</span>current<span class="token punctuation">.</span>value<span class="token punctuation">)</span>
        
        <span class="token keyword">return</span> <span class="token punctuation">(</span>
          <span class="token operator">&lt;</span>div<span class="token operator">&gt;</span>
            评价：<span class="token operator">&lt;</span>Input inputRef<span class="token operator">=</span><span class="token punctuation">{</span>inputRef<span class="token punctuation">}</span><span class="token operator">/</span><span class="token operator">&gt;</span>
            <span class="token operator">&lt;</span>button onClick<span class="token operator">=</span><span class="token punctuation">{</span>onSubmit<span class="token punctuation">}</span><span class="token operator">&gt;</span>提交<span class="token operator">&lt;</span><span class="token operator">/</span>button<span class="token operator">&gt;</span>
          <span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">&gt;</span>
        <span class="token punctuation">)</span>
      <span class="token punctuation">}</span>
      <span class="token function">render</span><span class="token punctuation">(</span>
        <span class="token operator">&lt;</span>App<span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">,</span>
        document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span>
      <span class="token punctuation">)</span><span class="token punctuation">;</span>

    </span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>当然React.forwardRef还可以用于高阶组件中，这里不再赘述，请参考官方文档 <a href="https://reactjs.org/docs/forwarding-refs.html" target="_blank" rel="noopener noreferrer">Forwarding Refs<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>。</p> <h3 id="react-createref-vs-react-useref"><a href="#react-createref-vs-react-useref" class="header-anchor">#</a> React.createRef vs React.useRef</h3> <p>细心的读者可能会发现在上面代码App中我们分别使用React.createRef和React.useRef两种方式创建了ref，都能实现我们想要的效果。那么它俩有什么区别呢？</p> <ol><li>useRef不能用在类组件中，如下代码会报错：</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">super</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span>
    <span class="token comment">// Invalid hook call. Hooks can only be called inside of the body of a function component.</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>valRef <span class="token operator">=</span> <span class="token function">useRef</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token keyword">null</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><ol start="2"><li>useRef除了可以用于ref属性，它还可以保存任何可变值，类似于一个 class 的实例属性，并且可以通过参数传入初始值createRef则不可以传默认值。</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">App</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> <span class="token punctuation">[</span><span class="token punctuation">,</span> setCount<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token keyword">let</span> count <span class="token operator">=</span> <span class="token function">useRef</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span>
  <span class="token keyword">const</span> <span class="token function-variable function">handleClick</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    count<span class="token punctuation">.</span>current <span class="token operator">+=</span> <span class="token number">1</span>
    <span class="token function">setCount</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">return</span> <span class="token operator">&lt;</span>span onClick<span class="token operator">=</span><span class="token punctuation">{</span>handleClick<span class="token punctuation">}</span><span class="token operator">&gt;</span><span class="token punctuation">{</span>count<span class="token punctuation">.</span>current<span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>span<span class="token operator">&gt;</span>
<span class="token punctuation">}</span>
</code></pre></div><ol start="3"><li>useRef 会在每次渲染时返回同一个 ref 对象，它将会在函数组件的生命周期中，保持状态不变，除非手动进行修改，createRef创建的值会随着函数组件渲染时重复执行而不断被初始化。</li></ol> <p>当我们将上例中的useRef换成createRef再点击span标签，控制台输出的是null，这是怎么回事呢？</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">App</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> <span class="token punctuation">[</span><span class="token punctuation">,</span> setCount<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token keyword">let</span> count <span class="token operator">=</span> <span class="token function">createRef</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token keyword">const</span> <span class="token function-variable function">handleClick</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>count<span class="token punctuation">)</span><span class="token punctuation">;</span>
    count<span class="token punctuation">.</span>current <span class="token operator">+=</span> <span class="token number">1</span>
    <span class="token function">setCount</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">return</span> <span class="token operator">&lt;</span>span onClick<span class="token operator">=</span><span class="token punctuation">{</span>handleClick<span class="token punctuation">}</span><span class="token operator">&gt;</span><span class="token number">123</span><span class="token punctuation">{</span>count<span class="token punctuation">.</span>current<span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>span<span class="token operator">&gt;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>这是因为App组件是函数组件，每次渲染、更新时都要将App函数从头到尾执行一遍，createRef返回的值每次都是{current: null}。createRef能在类组件中使用是因为类组件中有明确的生命周期钩子函数，组件渲染时不会不会将类中所有的变量、方法都重新执行、初始化。</p> <ol start="4"><li>当 ref 对象内容发生变化时，useRef 并不会通知你。变更 .current 属性不会引发组件重新渲染。如果想要在 React 绑定或解绑 DOM 节点的 ref 时运行某些代码，则需要使用回调 ref 来实现。</li></ol> <div class="language-js extra-class"><pre class="language-js"><code>
</code></pre></div><p>参考：</p> <p><a href="https://overreacted.io/zh-hans/how-are-function-components-different-from-classes/" target="_blank" rel="noopener noreferrer">函数式组件与类组件有何不同？<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p><a href="https://zhuanlan.zhihu.com/p/115230135" target="_blank" rel="noopener noreferrer">分析React.createRef和React.useRef<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p><a href="https://zhuanlan.zhihu.com/p/266195161" target="_blank" rel="noopener noreferrer">React Ref 原来是这样的<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p><a href="https://zhuanlan.zhihu.com/p/40462264" target="_blank" rel="noopener noreferrer">React ref 的前世今生<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p><a href="https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/" target="_blank" rel="noopener noreferrer">React生命周期网址<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p><a href="https://github.com/wojtekmaj/react-lifecycle-methods-diagram" target="_blank" rel="noopener noreferrer">React生命周期项目github地址<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p><a href="https://www.jianshu.com/p/514fe21b9914" target="_blank" rel="noopener noreferrer">详解React生命周期<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p><a href="https://zhuanlan.zhihu.com/p/38030418" target="_blank" rel="noopener noreferrer">React v16.3之后的组件生命周期函数<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p></div> <footer class="page-edit"><!----> <!----></footer> <div class="page-nav"><p class="inner"><!----> <span class="next"><a href="/books/深入React技术栈/02.html">
        漫谈React
      </a>
      →
    </span></p></div> </main></div><div class="global-ui"><!----><!----></div></div>
    <script src="/assets/js/app.8c5a7a92.js" defer></script><script src="/assets/js/2.8e30e130.js" defer></script><script src="/assets/js/40.fcf089d7.js" defer></script><script src="/assets/js/64.0323ed89.js" defer></script>
  </body>
</html>
